chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / stuff.c
CommitLineData
69695f33
MW
1/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005 by Arkkra Enterprises */
2/* All rights reserved */
3/*
4 * Name: stuff.c
5 *
6 * Description: This file contains functions for handling "stuff".
7 */
8
9#include "defines.h"
10#include "structs.h"
11#include "globals.h"
12
13/* for STUFF, apply appropriate staffscale, based on "all" */
14#define STUFFSTEP(stuff_p) ((stuff_p)->all == YES ? \
15 Score.staffscale * STEPSIZE : stepsize);
16
17static void normalizestuff P((void));
18static void movestuff P((struct STAFF *staff1_p, struct STAFF *staff2_p,
19 struct STUFF *stuff_p));
20static void setphrases P((void));
21static void phrasestuff P((struct MAINLL *msbeg_p, struct STUFF *stuff_p));
22static void set1phrase P((struct MAINLL *msbeg_p, struct STUFF *stuff_p,
23 int v));
24static void rmstuff P((struct STAFF *staff_p, struct STUFF *stuff_p));
25static void breakstuff P((void));
26static struct STUFF *prevstuff P((struct MAINLL *mainll_p,
27 struct STUFF *stuff_p));
28static void breakone P((struct MAINLL *m2_p, struct STUFF *stuff_p,
29 int timenum, char *origstr_p, int depth));
30static void contpedal P((void));
31static void setstuff P((void));
32static double count2coord P((double count, struct BAR *bar_p,
33 struct CHHEAD *chhead_p, int timeden));
34static int geteast P((struct STUFF *stuff_p, struct MAINLL *m2_p,
35 short *timeden2_p, struct CHHEAD **chhead2_p_p,
36 struct BAR **bar2_p_p));
37static int setmrferm P((struct STAFF *staff_p, struct STUFF *stuff_p));
38static int trygrid P((struct MAINLL *mainll_p, struct STUFF *stuff_p));
39static void tieslurstuff P((void));
40static void mktieslurstuff P((struct MAINLL *mllstaff_p, struct GRPSYL *gs_p,
41 int n, int s));
42static void mkextrastuff P((struct MAINLL *mll_p, struct STUFF *origstuff_p,
43 struct GRPSYL *gs_p, int n, int s, int stufftype));
44\f
45/*
46 * Name: stuff()
47 *
48 * Abstract: Perform all necessary horizontal operations on STUFF.
49 *
50 * Returns: void
51 *
52 * Description: This function calls subroutines to do all necessary horizontal
53 * operations on STUFF.
54 */
55
56void
57stuff()
58{
59 debug(16, "stuff");
60 normalizestuff();
61 setphrases();
62 breakstuff();
63 contpedal();
64 setstuff();
65 tieslurstuff();
66}
67\f
68/*
69 * Name: normalizestuff()
70 *
71 * Abstract: Normalize STUFF starting at count N + 1 before a FEED.
72 *
73 * Returns: void
74 *
75 * Description: This function looks for all STUFF structures that start at
76 * count N + 1 (where N is the numerator of the time signature)
77 * in measures preceding a score feed. These things really
78 * should be drawn at the start of the next score, so this
79 * function moves them to be at count 0 of the next measure.
80 * However, if the staff involved is invisible on the next score,
81 * it doesn't move the STUFF. Also, fermatas and the pedal marks
82 * PEDAL and ENDPED are not moved.
83 * Only start.count is used; the policy is to apply start.steps
84 * only after everything else is done.
85 */
86
87static void
88normalizestuff()
89{
90 struct MAINLL *mainll_p; /* point along main linked list */
91 struct MAINLL *m2_p, *m3_p; /* secondary & tertiary MLL pointers */
92 struct STUFF *stuff_p; /* point at a STUFF structure */
93 struct STUFF *next_p; /* point at the next STUFF structure */
94
95
96 debug(16, "normalizestuff");
97 initstructs();
98
99 /*
100 * Loop through the main linked list, looking for BARs that immediately
101 * precede a FEED. When found, adjust the start count of STUFFs in the
102 * preceding measure if necessary.
103 */
104 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
105
106 switch (mainll_p->str) {
107 case S_SSV:
108 /* keep SSVs up to date; we need to know time sig */
109 asgnssv(mainll_p->u.ssv_p);
110 continue;
111
112 case S_BAR:
113 /* break out to handle this BAR */
114 break;
115
116 default:
117 /* nothing to do, skip to next loop */
118 continue;
119 }
120
121 /*
122 * Find out if this is a bar that immediately precedes a FEED.
123 * If not, there is no need to adjust any stuff, so continue.
124 */
125 for (m2_p = mainll_p; m2_p != 0 && m2_p->str != S_FEED &&
126 m2_p->str != S_CHHEAD; m2_p = m2_p->next)
127 ;
128 if (m2_p == 0 || m2_p->str == S_CHHEAD)
129 continue;
130
131 /*
132 * This bar immediately precedes a FEED. Make sure the number
133 * of staffs doesn't change across this FEED. (And if what
134 * follows are blocks, continue looking until we find a FEED
135 * that is not a block.) If it does, don't move any STUFF.
136 */
137 for (m2_p = mainll_p; m2_p->next != 0; m2_p = m2_p->next) {
138 /* break out if a FEED that is not followed by block */
139 if (m2_p->str == S_FEED &&
140 m2_p->next->str != S_BLOCKHEAD)
141 break;
142 /* break out if SSV changes number of staffs */
143 if (m2_p->str == S_SSV &&
144 m2_p->u.ssv_p->used[NUMSTAFF] == YES)
145 break;
146 }
147 /* if at end of list or staffs changed, don't move stuff */
148 if (m2_p->next == 0 || m2_p->str == S_SSV)
149 continue;
150
151 /*
152 * Search back to the CHHEAD of the preceding measure.
153 */
154 for (m2_p = mainll_p; m2_p->str != S_CHHEAD; m2_p = m2_p->prev)
155 ;
156
157 /*
158 * Loop through all the staffs in this preceding measure,
159 * adjusting STUFF when need be.
160 */
161 for (m2_p = m2_p->next; m2_p->str == S_STAFF;
162 m2_p = m2_p->next) {
163
164 if (m2_p->u.staff_p->visible == NO)
165 continue;
166
167 /*
168 * Find the matching STAFF in the next measure. If we
169 * can't find it (like end of MLL) or it's not visible,
170 * forget this staff.
171 */
172 for (m3_p = mainll_p->next; m3_p != 0 &&
173 m3_p->str != S_BAR; m3_p = m3_p->next) {
174 if (m3_p->str == S_STAFF &&
175 m3_p->u.staff_p->staffno ==
176 m2_p->u.staff_p->staffno)
177 break;
178 }
179 if (m3_p == 0 || m3_p->str != S_STAFF ||
180 m3_p->u.staff_p->visible == NO)
181 continue;
182
183 /*
184 * Loop through all the stuff on this staff in the
185 * preceding measure, normalizing it. That is, if it
186 * starts at count N + 1 (where N is the numerator of
187 * the time signature), change it to start at count 0
188 * of the next bar line. However, don't move fermatas
189 * or pedal "bounce" or "ending" marks.
190 */
191 for (stuff_p = m2_p->u.staff_p->stuff_p;
192 stuff_p != 0; stuff_p = next_p) {
193 /*
194 * Remember next one in case we have to move
195 * this one to the next measure's linked list.
196 */
197 next_p = stuff_p->next;
198
199 if (stuff_p->start.count == Score.timenum + 1 &&
200 string_is_sym(stuff_p->string, C_PEDAL, FONT_MUSIC) == NO &&
201 string_is_sym(stuff_p->string, C_ENDPED, FONT_MUSIC) == NO &&
202 string_is_sym(stuff_p->string, C_FERM, FONT_MUSIC) == NO &&
203 string_is_sym(stuff_p->string, C_UFERM, FONT_MUSIC) == NO) {
204 /*
205 * Move this stuff from preceding to
206 * following measure's linked list.
207 */
208 movestuff(m2_p->u.staff_p,
209 m3_p->u.staff_p, stuff_p);
210 /*
211 * Set start count to 0. If there is a
212 * "til" clause, bars would have to be
213 * greater than 0, since count can't
214 * refer to a count in this measure
215 * (can't be greater than N + 1). So
216 * we only need to check bars to see if
217 * there's a "til" clause. If there
218 * is, decrement it.
219 */
220 stuff_p->start.count = 0;
221 if (stuff_p->end.bars > 0)
222 stuff_p->end.bars--;
223 }
224 }
225 }
226 }
227}
228\f
229/*
230 * Name: movestuff()
231 *
232 * Abstract: Move a STUFF from one linked list to another.
233 *
234 * Returns: void
235 *
236 * Description: This function, given two staff pointers, finds the given STUFF
237 * in the first one's linked list of STUFF. It removes it from
238 * there and adds it to the start of the second staff's list.
239 */
240
241static void
242movestuff(staff1_p, staff2_p, stuff_p)
243
244struct STAFF *staff1_p; /* first STAFF */
245struct STAFF *staff2_p; /* second STAFF */
246struct STUFF *stuff_p; /* the STUFF to be moved */
247
248{
249 struct STUFF *s_p; /* loop pointer */
250
251
252 debug(32, "movestuff file=%s line=%d", stuff_p->inputfile,
253 stuff_p->inputlineno);
254 if (staff1_p->stuff_p == stuff_p) {
255 /*
256 * This STUFF is the first one in the first STAFF's linked
257 * list. Change the headcell to point at the next one (which
258 * removes it from this list). This "next one" could be null.
259 */
260 staff1_p->stuff_p = stuff_p->next;
261 } else {
262 /*
263 * Find which STUFF in the first STAFF's list points at the one
264 * we want to move. Make it point at the following one.
265 */
266 for (s_p = staff1_p->stuff_p; s_p->next != stuff_p;
267 s_p = s_p->next)
268 ;
269 s_p->next = stuff_p->next;
270 }
271
272 /*
273 * Make the STUFF we are moving point at what used to be the first
274 * one in the second STAFF's linked list. Make the second STAFF's
275 * headcell point at the STUFF we are moving.
276 */
277 stuff_p->next = staff2_p->stuff_p;
278 staff2_p->stuff_p = stuff_p;
279}
280\f
281/*
282 * Name: setphrases()
283 *
284 * Abstract: Find endpoints and direction of all phrase marks.
285 *
286 * Returns: void
287 *
288 * Description: This function loops through the main linked list and all STUFF,
289 * looking for phrase marks. For each phrase mark, it calls
290 * phrasestuff() to find out the horizontal positioning of the
291 * endpoints and whether the phrase mark should be above or below.
292 */
293
294static void
295setphrases()
296{
297 struct MAINLL *mainll_p; /* point along main linked list */
298 struct STUFF *stuff_p; /* point at a STUFF structure */
299 struct STUFF **phrasearray; /* malloc array of pointers to stuff */
300 int numphrases; /* number of phrases in linked list */
301 int n; /* loop through phrasearray */
302
303
304 debug(16, "setphrases");
305 initstructs();
306
307 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
308
309 switch (mainll_p->str) {
310 case S_SSV:
311 /* keep SSVs up to date; we need to know time sig */
312 asgnssv(mainll_p->u.ssv_p);
313 continue;
314
315 case S_STAFF:
316 /* break out to handle this STAFF */
317 break;
318
319 default:
320 /* nothing to do, skip to next loop */
321 continue;
322 }
323
324 /*
325 * For each phrase in this staff's stuff list, we need to
326 * determine whether it should print 0, 1, or 2 phrase marks,
327 * and the direction and endpoints of each. We can't simply
328 * loop through the linked list, because the list gets altered
329 * by the subroutines we call, which can add and delete phrases
330 * from the list. So we copy the pointers to an array first.
331 */
332 /* count how many phrases are in this staff's stuff list */
333 numphrases = 0;
334 for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
335 stuff_p = stuff_p->next) {
336 if (stuff_p->stuff_type == ST_PHRASE)
337 numphrases++;
338 }
339
340 /* if no phrases, nothing to do */
341 if (numphrases == 0)
342 continue;
343
344 /* allocate an array to hold pointer(s) to the phrase(s) */
345 MALLOCA(struct STUFF *, phrasearray, numphrases);
346
347 /* fill the array with pointers to each phrase */
348 n = 0;
349 for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
350 stuff_p = stuff_p->next) {
351 if (stuff_p->stuff_type == ST_PHRASE)
352 phrasearray[n++] = stuff_p;
353 }
354
355 /* find endpoints and direction of phrase(s) from each stuff */
356 for (n = 0; n < numphrases; n++) {
357 phrasestuff(mainll_p, phrasearray[n]);
358 }
359
360 FREE(phrasearray);
361 }
362}
363\f
364/*
365 * Name: phrasestuff()
366 *
367 * Abstract: Find endpoints and direction of phrase(s) from one STUFF.
368 *
369 * Returns: void
370 *
371 * Description: This function decides whether the given phrase STUFF should
372 * try to generate one or two phrase marks above, below, or both.
373 * If it's both, it inserts a new STUFF in the list for it. Then
374 * it calls set1phrase() for each desired phrase to find endpoints
375 * and set the place if it's unknown.
376 */
377
378static void
379phrasestuff(msbeg_p, stuff_p)
380
381struct MAINLL *msbeg_p; /* point at main linked list where phrase starts */
382struct STUFF *stuff_p; /* point at STUFF structure for start of phrase */
383
384{
385 struct STUFF *stuff2_p; /* if we need to create a 2nd phrase */
386
387
388 debug(32, "phrasestuff file=%s line=%d", stuff_p->inputfile,
389 stuff_p->inputlineno);
390 switch (svpath(msbeg_p->u.staff_p->staffno, VSCHEME)->vscheme) {
391 case V_1: /* one voice */
392 /* do phrase mark for first (only) voice if possible */
393 set1phrase(msbeg_p, stuff_p, 0);
394 break;
395
396 case V_2FREESTEM: /* two voices that are free if one is space */
397 case V_3FREESTEM: /* same as above; STUFF ignores voice 3 */
398 if (chkallspace(msbeg_p, stuff_p, 0) == YES) {
399 /* first voice all spaces, apply phrase to second */
400 set1phrase(msbeg_p, stuff_p, 1);
401 break;
402 } else if (chkallspace(msbeg_p, stuff_p, 1) == YES) {
403 /* second voice all spaces, apply phrase to first */
404 set1phrase(msbeg_p, stuff_p, 0);
405 break;
406 }
407 /* FALL THROUGH to handle like V_2OPSTEM */
408
409 case V_2OPSTEM: /* two voices that always oppose */
410 case V_3OPSTEM: /* same as above; STUFF ignores voice 3 */
411 switch (stuff_p->place) {
412
413 case PL_ABOVE:
414 /* phrase requested only for top voice */
415 set1phrase(msbeg_p, stuff_p, 0);
416 break;
417
418 case PL_BELOW:
419 /* phrase requested only for bottom voice */
420 set1phrase(msbeg_p, stuff_p, 1);
421 break;
422
423 default:
424 /*
425 * We're going to have two phrase marks, one above the
426 * first voice and one below the second voice. Let the
427 * current STUFF be for the top one, and create a new
428 * STUFF for the bottom one.
429 */
430 stuff_p->place = PL_ABOVE;
431 stuff2_p = newSTUFF((char *)0,
432 stuff_p->dist,
433 stuff_p->dist_usage,
434 stuff_p->start.count,
435 stuff_p->start.steps,
436 stuff_p->gracebackup,
437 stuff_p->end.bars, stuff_p->end.count,
438 ST_PHRASE, NO, PL_BELOW,
439 stuff_p->inputfile,
440 stuff_p->inputlineno);
441 stuff2_p->next = stuff_p->next;
442 stuff_p->next = stuff2_p;
443
444 set1phrase(msbeg_p, stuff_p, 0);
445 set1phrase(msbeg_p, stuff2_p, 1);
446 break;
447 }
448 break;
449 }
450}
451\f
452/*
453 * Name: set1phrase()
454 *
455 * Abstract: Find endpoints and direction of one phrase.
456 *
457 * Returns: void
458 *
459 * Description: This function, given a STUFF for a single phrase mark and the
460 * voice it should apply to, finds the endpoint GRPSYLs for the
461 * phrase. If it can't find valid GRPSYLs, it removes the phrase
462 * and prints a warning. Otherwise, it also decides whether the
463 * phrase should be above or below, if that is not already known.
464 */
465
466static void
467set1phrase(msbeg_p, stuff_p, v)
468
469struct MAINLL *msbeg_p; /* point at MLL (staff) where phrase begins */
470struct STUFF *stuff_p; /* point at STUFF structure for start of phrase */
471int v; /* which voice to attach the phrase to */
472
473{
474 struct MAINLL *msend_p; /* MLL (staff) where phrase ends */
475 struct MAINLL *mll_p; /* for looping through MLL */
476 struct GRPSYL *beggrp_p;/* (eventually is) beginning of phrase */
477 struct GRPSYL *endgrp_p;/* (eventually is) end of phrase */
478 struct GRPSYL *gs_p; /* for looping through GRPSYL lists */
479 int staffno; /* the staff this phrase is on */
480 int timeden; /* denominator of time sig at end of phrase */
481 int up, down; /* count stem directions */
482 int n; /* loop variable */
483
484
485 debug(32, "set1phrase file=%s line=%d v=%d", stuff_p->inputfile,
486 stuff_p->inputlineno, v);
487 stuff_p->vno = v + 1; /* translate voice numbers 0, 1 to 1, 2 */
488 staffno = msbeg_p->u.staff_p->staffno;
489
490 /*
491 * Find what measure this phrase mark ends in. Along the way, keep
492 * track of the time signature denominator, in case it changes. If
493 * getendstuff() returns 0, it means the phrase runs into a multirest,
494 * which is not allowed. If the phrase is supposed to be attached to
495 * the bottom voice, but it ends in a measure where the vscheme is 1,
496 * we must also throw it away. (This condition is signaled by the
497 * groups_p[v] being a null pointer.)
498 */
499 msend_p = getendstuff(msbeg_p, stuff_p, &timeden);
500
501 if (msend_p == 0) {
502 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
503 "removing invalid phrase (runs into multirest)");
504 rmstuff(msbeg_p->u.staff_p, stuff_p);
505 return;
506 }
507 if (msend_p->u.staff_p->groups_p[v] == 0) {
508 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
509 "removing invalid phrase (covers no notes in last measure)");
510 rmstuff(msbeg_p->u.staff_p, stuff_p);
511 return;
512 }
513
514 /*
515 * Find the GRPSYLs that are closest, timewise, to the requested
516 * beginning and ending times of the phrase mark.
517 */
518 beggrp_p = closestgroup(stuff_p->start.count,
519 msbeg_p->u.staff_p->groups_p[v], Score.timeden);
520 endgrp_p = closestgroup(stuff_p->end.count,
521 msend_p->u.staff_p->groups_p[v], timeden);
522
523 /*
524 * It's possible that *beggrp_p is a rest or a space, but a phrase must
525 * start on a note group. So search forward, if necessary, to the first
526 * note group after this point. If there is none in this measure, this
527 * is an illegal phrase mark. Also, if the phrase begins and ends in
528 * the same measure, check that we don't go past the end in doing this
529 * search. A phrase is not allowed to begin and end at the same group.
530 * But the two groups can be the same if gracebackup is being used,
531 * because in that case the beginning group is really a grace group
532 * before the ending group. In any case, apply gracebackup if
533 * requested.
534 */
535 while (beggrp_p != 0 && beggrp_p->grpcont != GC_NOTES) {
536 if (beggrp_p == endgrp_p)
537 break;
538 beggrp_p = nextnongrace(beggrp_p);
539 }
540 if (beggrp_p == 0) {
541 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
542 "removing invalid phrase (covers no notes in first measure)");
543
544 rmstuff(msbeg_p->u.staff_p, stuff_p);
545 return;
546 }
547 if (beggrp_p == endgrp_p && stuff_p->gracebackup == 0) {
548 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
549 "removing invalid phrase (need multiple notes)");
550
551 rmstuff(msbeg_p->u.staff_p, stuff_p);
552 return;
553 }
554 /* found a valid starting point; back up grace notes if requested */
555 for (n = 0; n < stuff_p->gracebackup; n++) {
556 beggrp_p = beggrp_p->prev;
557 if (beggrp_p == 0 || beggrp_p->grpvalue != GV_ZERO) {
558 l_ufatal(stuff_p->inputfile, stuff_p->inputlineno,
559 "not enough grace groups to back up to for phrase");
560 }
561 }
562
563 /*
564 * Do the equivalent thing with the end of the phrase mark, except that
565 * we don't have to deal with gracebackup.
566 */
567 while (endgrp_p != 0 && endgrp_p->grpcont != GC_NOTES &&
568 beggrp_p != endgrp_p) {
569 endgrp_p = prevnongrace(endgrp_p);
570 }
571 if (beggrp_p == endgrp_p) {
572 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
573 "removing invalid phrase (need multiple notes)");
574
575 rmstuff(msbeg_p->u.staff_p, stuff_p);
576 return;
577 }
578 if (endgrp_p == 0) {
579 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
580 "removing invalid phrase (covers no notes in last measure)");
581
582 rmstuff(msbeg_p->u.staff_p, stuff_p);
583 return;
584 }
585
586 /*
587 * We have now determined the correct beginning and ending GRPSYLs for
588 * the phrase. Store them for later use.
589 */
590 stuff_p->beggrp_p = beggrp_p;
591 stuff_p->endgrp_p = endgrp_p;
592
593 /*
594 * If we don't know yet whether the phrase should be drawn above or
595 * below the staff, decide that now. We will put it on the side that
596 * has more note heads than stems. So loop through all GRPSYLs within
597 * this phrase, counting. Ignore grace groups.
598 */
599 if (stuff_p->place == PL_UNKNOWN) {
600 up = down = 0;
601 mll_p = msbeg_p;
602 gs_p = beggrp_p;
603 if (gs_p->grpvalue == GV_ZERO)
604 gs_p = nextnongrace(gs_p);
605 while (gs_p != endgrp_p) {
606 if (gs_p->grpcont == GC_NOTES) {
607 if (gs_p->stemdir == UP)
608 up++;
609 else
610 down++;
611 }
612
613 gs_p = nextnongrace(gs_p);
614
615 /* if we hit the end of a measure, find start of next */
616 if (gs_p == 0) {
617 for (mll_p = mll_p->next;
618 mll_p->str != S_STAFF ||
619 mll_p->u.staff_p->staffno != staffno;
620 mll_p = mll_p->next)
621 ;
622 gs_p = mll_p->u.staff_p->groups_p[v];
623 }
624 }
625 /* count final group in phrase (must be GC_NOTES) */
626 if (gs_p->stemdir == UP)
627 up++;
628 else
629 down++;
630
631 /*
632 * Put phrase opposite the majority of the stems. If it's a
633 * tie, base it on the first group.
634 */
635 if (up > down)
636 stuff_p->place = PL_BELOW;
637 else if (up < down)
638 stuff_p->place = PL_ABOVE;
639 else if (beggrp_p->stemdir == UP)
640 stuff_p->place = PL_BELOW;
641 else
642 stuff_p->place = PL_ABOVE;
643 }
644}
645\f
646/*
647 * Name: rmstuff()
648 *
649 * Abstract: Remove a STUFF from a linked list, and free it.
650 *
651 * Returns: void
652 *
653 * Description: This function removes the given STUFF from the linked list
654 * hanging off the given staff, and frees it.
655 */
656
657static void
658rmstuff(staff_p, stuff_p)
659
660struct STAFF *staff_p; /* the staff that the stuff hangs off of */
661struct STUFF *stuff_p; /* the stuff to be removed */
662
663{
664 struct STUFF *stuff2_p; /* point along STUFF list */
665
666
667 debug(32, "rmstuff file=%s line=%d", stuff_p->inputfile,
668 stuff_p->inputlineno);
669 if (staff_p->stuff_p == stuff_p) {
670 /* the given stuff is the first one in the list */
671 staff_p->stuff_p = stuff_p->next;
672 } else {
673 /* find which stuff in list points at the one to be removed */
674 for (stuff2_p = staff_p->stuff_p; stuff2_p->next != stuff_p;
675 stuff2_p = stuff2_p->next)
676 ;
677 stuff2_p->next = stuff_p->next;
678 }
679
680 FREE(stuff_p);
681}
682\f
683/*
684 * Name: breakstuff()
685 *
686 * Abstract: Break all "stuff" that crosses scorefeeds.
687 *
688 * Returns: void
689 *
690 * Description: This function loops through the main linked list and all STUFF,
691 * looking for stuff that crosses score feeds. When it finds such
692 * stuff, it breaks them at that point.
693 */
694
695static void
696breakstuff()
697{
698 struct MAINLL *mainll_p; /* point along main linked list */
699 struct STUFF *stuff_p; /* point at a STUFF structure */
700
701
702 debug(16, "breakstuff");
703 initstructs();
704
705 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
706
707 switch (mainll_p->str) {
708 case S_SSV:
709 /* keep SSVs up to date; we need to know time sig */
710 asgnssv(mainll_p->u.ssv_p);
711 continue;
712
713 case S_STAFF:
714 /* break out to handle this STAFF */
715 break;
716
717 default:
718 /* nothing to do, skip to next loop */
719 continue;
720 }
721
722 /*
723 * Loop through all the stuff on this staff. Do it in reverse
724 * order so that when stuff gets broken, the new STUFFs end up
725 * in the correct order.
726 */
727 if (mainll_p->u.staff_p->stuff_p != 0) {
728
729 stuff_p = mainll_p->u.staff_p->stuff_p;
730 while (stuff_p->next != 0)
731 stuff_p = stuff_p->next;
732 /* now stuff_p points at the last one in the list */
733
734 for ( ; stuff_p != 0; stuff_p = prevstuff(mainll_p,
735 stuff_p)) {
736 /*
737 * If there's a "til" clause, and it crosses
738 * bar lines, call a function to see if it
739 * needs to be broken, and if so, break it.
740 */
741 if (stuff_p->end.bars > 0)
742 breakone(mainll_p, stuff_p,
743 Score.timenum,
744 stuff_p->string, 1);
745 }
746 }
747 }
748}
749\f
750/*
751 * Name: prevstuff()
752 *
753 * Abstract: Find stuff preceding the given one.
754 *
755 * Returns: pointer to previous stuff, or 0 if none
756 *
757 * Description: This function is given a pointer to a staff mainll item and a
758 * stuff in that list. It finds the preceding stuff, returning
759 * it, or 0 if none. If stuff linked lists were doubly linked,
760 * we wouldn't have to go through this aggravation.
761 */
762
763static struct STUFF *
764prevstuff(mainll_p, stuff_p)
765
766struct MAINLL *mainll_p; /* ptr to MLL item for a stuff */
767struct STUFF *stuff_p; /* ptr to current stuff */
768
769{
770 register struct STUFF *prevstuff_p;
771
772
773 prevstuff_p = mainll_p->u.staff_p->stuff_p; /* get 1st stuff in list */
774
775 /* if current stuff is first stuff, there is none before it */
776 if (prevstuff_p == stuff_p)
777 return (0);
778
779 /* loop until we find it, then return */
780 while (prevstuff_p->next != stuff_p)
781 prevstuff_p = prevstuff_p->next;
782 return (prevstuff_p);
783}
784\f
785/*
786 * Name: breakone()
787 *
788 * Abstract: Break one "stuff" item if it crosses scorefeeds.
789 *
790 * Returns: void
791 *
792 * Description: This function is given a STUFF with a "til" clause that crosses
793 * bar line(s). It finds out if the STUFF crosses the FEED at the
794 * end of the score. If so, it stops the current stuff there, and
795 * starts a continuation on the next score. If there are more bar
796 * lines yet to be crossed, it calls itself recursively.
797 */
798
799static void
800breakone(mllstaff_p, stuff_p, timenum, origstr_p, depth)
801
802struct MAINLL *mllstaff_p; /* point at MLL struct holding stuff's staff */
803struct STUFF *stuff_p; /* point at a STUFF structure */
804int timenum; /* numerator of current time sig */
805char *origstr_p; /* original string, from first score of stuff */
806int depth; /* depth of recursion */
807
808{
809 /*
810 * Make the local variables static, to use less stack when making
811 * recursive calls. We can get away with this because the recursive
812 * call is at the end of the function, and the variables aren't used
813 * after that.
814 */
815 static struct MAINLL *m2_p; /* point along main linked list */
816 static struct MAINLL *m3_p; /* point along main linked list */
817 static struct MAINLL *m4_p; /* point along main linked list */
818 static struct STUFF *s_p; /* point at a new STUFF */
819 static struct GRPSYL *gs_p; /* point along a GRPSYL list */
820 static int bars; /* count how many bars long it is */
821 static int otimenum; /* num of time sig before last bar */
822 static float endcount; /* count where the stuff ends */
823
824
825 debug(32, "breakone file=%s line=%d timenum=%d origstr_p=\"%s\"",
826 stuff_p->inputfile, stuff_p->inputlineno, timenum,
827 origstr_p == 0 ? "" : origstr_p);
828 /*
829 * Save how many bars this stuff crosses (initially, before any
830 * breaking), and the count where it ends.
831 */
832 bars = stuff_p->end.bars;
833 endcount = stuff_p->end.count;
834
835 /*
836 * Loop forward until crossing the given number of bars, or hitting a
837 * FEED, whichever comes first. Keep the timenum updated. At each
838 * bar line, save what it was before in otimenum.
839 */
840 for (m2_p = mllstaff_p; bars >= 0 && m2_p != 0 && m2_p->str != S_FEED;
841 m2_p = m2_p->next) {
842
843 switch (m2_p->str) {
844 case S_SSV:
845 if (m2_p->u.ssv_p->used[TIME] == YES)
846 timenum = m2_p->u.ssv_p->timenum;
847 break;
848
849 case S_BAR:
850 otimenum = timenum;
851 bars--;
852 break;
853
854 case S_STAFF:
855 /*
856 * If this is the first staff of a measure, check the
857 * first voice to see if it's a multirest. (If it is,
858 * all voices on all staffs would be.) If so, decrement
859 * the bars remaining appropriately. It could end up
860 * less than 0. That's okay; we won't be breaking it.
861 */
862 if (m2_p->u.staff_p->staffno == 1 &&
863 m2_p->u.staff_p->groups_p[0]->basictime < -1) {
864
865 bars += 1 + m2_p->u.staff_p->
866 groups_p[0]->basictime;
867 }
868 break;
869 }
870 }
871
872 /*
873 * If bars <= -1, this stuff doesn't reach the end of this score, so
874 * just return. If we hit the end of the piece, end the stuff at the
875 * last count of the last measure (thus the last bar line). The
876 * parser has already put out a warning for this.
877 * If the stuff ends at the pseudobar of the next score, make it end at
878 * the last bar of this score instead. However, phrases should not be
879 * adjusted this way, because under these conditions they will get
880 * pulled to the note at count 1.
881 */
882 if (bars <= -1)
883 return;
884 if (m2_p == 0 || bars == 0 && stuff_p->end.count == 0 &&
885 stuff_p->stuff_type != ST_PHRASE) {
886 stuff_p->end.bars -= bars + 1;
887 stuff_p->end.count = timenum + 1;
888 return;
889 }
890
891 /*
892 * At this point we know that the stuff truly crosses the FEED we're
893 * at, and we're going to have to break it. First, terminate the part
894 * of the stuff on this score and mark the carryout. (However, if the
895 * next staff starts with a multirest that fully contains the rest of
896 * the stuff, we'll cancel the carryout later and not insert a new
897 * stuff for continuation.)
898 */
899 stuff_p->end.bars -= bars + 1; /* only cross this many bars */
900 stuff_p->end.count = otimenum + 1; /* end at end of last measure*/
901 stuff_p->carryout = YES;
902
903 /*
904 * Find the matching STAFF in the next measure. It might not exist
905 * due to blocks.
906 */
907 for (m3_p = m2_p->next; m3_p != 0 && m3_p->str != S_BAR;
908 m3_p = m3_p->next) {
909 if (m3_p->str == S_STAFF && m3_p->u.staff_p->staffno ==
910 mllstaff_p->u.staff_p->staffno)
911 break;
912 }
913 if (m3_p == 0) {
914 return;
915 }
916 if (m3_p->str != S_STAFF)
917 pfatal("can't find staff in main linked list [breakone]");
918
919 /*
920 * If the staff has a multirest that's longer than the remaining
921 * length of the stuff, don't insert a new stuff; just get out now.
922 */
923 if (m3_p->u.staff_p->groups_p[0]->basictime < -1) {
924 if (bars < -(m3_p->u.staff_p->groups_p[0]->basictime)) {
925 stuff_p->carryout = NO; /* cancel the carryout */
926 return;
927 }
928 }
929
930 /*
931 * Create a new STUFF starting at count 0 of the new measure. Link it
932 * in to its STAFF and set fields appropriately.
933 */
934 s_p = newSTUFF(origstr_p, stuff_p->dist, stuff_p->dist_usage,
935 (double)0, (double)0, (short)0, bars, endcount,
936 stuff_p->stuff_type, stuff_p->modifier, stuff_p->place,
937 stuff_p->inputfile, stuff_p->inputlineno);
938 s_p->next = m3_p->u.staff_p->stuff_p;
939 m3_p->u.staff_p->stuff_p = s_p;
940 s_p->carryin = YES;
941 s_p->vno = stuff_p->vno; /* actually only needed for phrases */
942
943 switch (s_p->stuff_type) {
944 case ST_ROM:
945 case ST_BOLD:
946 case ST_ITAL:
947 case ST_BOLDITAL:
948 /*
949 * If this staff was visible on the previous score, we just
950 * want the continuation dashes on this score, not the original
951 * string, so we change the string in that case. (If the staff
952 * is also invisible on this score, we don't care what happens,
953 * so don't even check for that.) Otherwise, leave it alone.
954 * Also, all other types that have strings should always repeat
955 * them on each score, so leave them alone.
956 */
957 if (mllstaff_p->u.staff_p->visible == YES)
958 s_p->string = dashstr(stuff_p->string);
959 break;
960 case ST_PHRASE:
961 /*
962 * The new (2nd half of the) phrase mark has as its first group
963 * its voice's first GRPSYL in the new score. Its last group
964 * is the last GRPSYL of the entire phrase. The last group of
965 * the old (1st half of the) phrase mark is the last GRPSYL on
966 * that score for this voice.
967 */
968 s_p->beggrp_p = m3_p->u.staff_p->groups_p[ stuff_p->vno - 1 ];
969 s_p->endgrp_p = stuff_p->endgrp_p;
970 /* find matching staff in the measure before the FEED */
971 for (m4_p = m2_p; m4_p->str != S_STAFF ||
972 m4_p->u.staff_p->staffno !=
973 mllstaff_p->u.staff_p->staffno;
974 m4_p = m4_p->prev)
975 ;
976 /* find last group in the measure in that voice */
977 for (gs_p = m4_p->u.staff_p->groups_p[ stuff_p->vno - 1 ];
978 gs_p->next != 0; gs_p = gs_p->next)
979 ;
980 stuff_p->endgrp_p = gs_p;
981 break;
982 }
983
984 /*
985 * If there are still more bars to be crossed, call ourselves
986 * recursively to break the stuff again if necessary. But first check
987 * to see we aren't too deep in recursion, using too much stack.
988 */
989 if (s_p->end.bars > 0) {
990 if (depth >= 300)
991 l_ufatal(stuff_p->inputfile, stuff_p->inputlineno,
992 "stuff crosses more than 300 scores (break into shorter pieces)");
993 breakone(m3_p, s_p, timenum, origstr_p, depth + 1);
994 }
995}
996\f
997/*
998 * Name: contpedal()
999 *
1000 * Abstract: Insert pedal continuation STUFFs when needed.
1001 *
1002 * Returns: void
1003 *
1004 * Description: When a pedal is to be held down through a score feed, the
1005 * print phase needs to know where (vertically) to draw the pedal
1006 * line on the new score. There might not occur another pedal
1007 * character in the first measure there, or even on that whole
1008 * score. So whenever this happens, regardless of whether there
1009 * are already pedal characters on the new score, this function
1010 * inserts a new STUFF with a special, null pedal indication, at
1011 * count 0 of the first measure of the new score.
1012 */
1013
1014static void
1015contpedal()
1016
1017{
1018 short inpedal[MAXSTAFFS + 1]; /* does this staff have pedal on now?*/
1019 short snappedal[MAXSTAFFS + 1]; /* same, when an ending is entered */
1020 struct MAINLL *mainll_p; /* point along main linked list */
1021 struct MAINLL *m2_p; /* another pointer along MLL */
1022 struct STUFF *stuff_p; /* point at a STUFF structure */
1023 struct STUFF *stuff2_p; /* point at new STUFF structure */
1024 struct BAR *bar_p; /* point at a bar line */
1025 int inending; /* are we now in an ending? */
1026 int s; /* staff number */
1027
1028
1029 debug(16, "contpedal");
1030 /* init pedal state to NO for all staffs */
1031 for (s = 1; s <= MAXSTAFFS; s++)
1032 inpedal[s] = NO;
1033
1034 inending = NO;
1035
1036 /*
1037 * Loop through main linked list. For each STAFF found, update pedal
1038 * state when necessary. For each FEED found, if there's a pedal
1039 * crossing it, insert a pedal continuation. There is special work to
1040 * do when endings are encountered, since this can change pedal states.
1041 */
1042 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
1043
1044 switch (mainll_p->str) {
1045
1046 case S_STAFF:
1047 /*
1048 * Loop through all the stuff on this staff. Whenever
1049 * there's a pedal mark, update the state for that
1050 * staff, except that pedal up/down is irrelevant.
1051 */
1052 for (stuff_p = mainll_p->u.staff_p->stuff_p;
1053 stuff_p != 0; stuff_p = stuff_p->next) {
1054
1055 if (stuff_p->stuff_type != ST_PEDAL)
1056 continue;
1057
1058 if (string_is_sym(stuff_p->string,
1059 C_BEGPED, FONT_MUSIC) == YES)
1060 inpedal[mainll_p->u.staff_p->
1061 staffno] = YES;
1062
1063 else if (string_is_sym(stuff_p->string,
1064 C_ENDPED, FONT_MUSIC) == YES)
1065 inpedal[mainll_p->u.staff_p->
1066 staffno] = NO;
1067 }
1068 break;
1069
1070 case S_BAR:
1071 /*
1072 * When entering a second or later ending, the state of
1073 * all pedals must be set back to what they were when
1074 * entering the first ending.
1075 * First deal with the case where an ending starts at
1076 * the pseudobar after a feed. In that case, we need
1077 * to ignore any endending on the previous real bar.
1078 */
1079 bar_p = mainll_p->u.bar_p;
1080 for (m2_p = mainll_p->next; m2_p != 0 &&
1081 m2_p->str != S_BAR &&
1082 (m2_p->str != S_CLEFSIG ||
1083 m2_p->u.clefsig_p->bar_p == 0);
1084 m2_p = m2_p->next)
1085 ;
1086 if (m2_p != 0 && m2_p->str == S_CLEFSIG) {
1087 /*
1088 * If an ending starts at this pseudobar,
1089 * substitute this pseudobar for the real one.
1090 */
1091 if (m2_p->u.clefsig_p->bar_p->endingloc
1092 == STARTITEM)
1093 bar_p = m2_p->u.clefsig_p->bar_p;
1094 }
1095
1096 switch (bar_p->endingloc) {
1097 case STARTITEM:
1098 if (inending == NO) {
1099 /* entering first ending */
1100 /* snapshot pedal states here */
1101 for (s = 1; s <= MAXSTAFFS; s++)
1102 snappedal[s] = inpedal[s];
1103 inending = YES;
1104 } else {
1105 /* entering a later ending */
1106 /* restore snapshotted state */
1107 for (s = 1; s <= MAXSTAFFS; s++)
1108 inpedal[s] = snappedal[s];
1109 }
1110 break;
1111
1112 case ENDITEM:
1113 /* leaving the last ending */
1114 inending = NO;
1115 break;
1116 }
1117 break;
1118
1119 case S_FEED:
1120 /* only consider FEEDs that are before music */
1121 if ( ! IS_CLEFSIG_FEED(mainll_p)) {
1122 break;
1123 }
1124
1125 /*
1126 * For every staff where the pedal is now down, find
1127 * the structure for that staff in the first measure,
1128 * and insert a STUFF to indicate the continuation of
1129 * the pedal mark line.
1130 */
1131 for (s = 1; s <= MAXSTAFFS; s++) {
1132
1133 if (inpedal[s] == NO)
1134 continue;
1135
1136 for (m2_p = mainll_p; m2_p != 0 &&
1137 (m2_p->str != S_STAFF ||
1138 m2_p->u.staff_p->staffno != s);
1139 m2_p = m2_p->next)
1140 ;
1141 if (m2_p == 0)
1142 pfatal("couldn't find staff in contpedal");
1143 /* pedal continuation at count 0, w/ null str */
1144 stuff2_p = newSTUFF((char *)0, 0, SD_NONE,
1145 (double)0, (double)0, (short)0, 0,
1146 (double)0, ST_PEDAL, NO, PL_BELOW,
1147 (char *)0, -1);
1148
1149 /* put at beginning of staff's linked list */
1150 stuff2_p->next = m2_p->u.staff_p->stuff_p;
1151 m2_p->u.staff_p->stuff_p = stuff2_p;
1152 }
1153 break;
1154 }
1155 }
1156}
1157\f
1158/*
1159 * Name: setstuff()
1160 *
1161 * Abstract: Set horizontal absolute coordinates of "stuff".
1162 *
1163 * Returns: void
1164 *
1165 * Description: This function loops through the main linked list. For every
1166 * visible staff, it loops through its list of STUFF structures,
1167 * setting all their absolute horizontal coordinates.
1168 */
1169
1170static void
1171setstuff()
1172
1173{
1174 struct MAINLL *mainll_p; /* point along main linked list */
1175 struct CHHEAD *chhead_p; /* chord headcell of current measure */
1176 struct BAR *bar_p; /* [pseudo] bar before current meas */
1177 struct STUFF *stuff_p; /* point at a STUFF structure */
1178 struct MAINLL *m2_p; /* MLL for end of stuff */
1179 short timeden2; /* time sig denom at end of stuff */
1180 struct CHHEAD *chhead2_p; /* chord headcell for end of stuff */
1181 struct BAR *bar2_p; /* bar line for end of stuff */
1182 struct GRPSYL *gs_p; /* used for gracebackup */
1183 float stepsize; /* STEPSIZE scaled by staffscale */
1184 float leftwid; /* width of string left of align pt. */
1185 float streast; /* east end of a string */
1186 int ret; /* return code from geteast */
1187 int v; /* voice associated with */
1188 int n; /* loop variable */
1189
1190
1191 debug(16, "setstuff");
1192 initstructs();
1193
1194 chhead_p = 0; /* prevent useless 'used before set' warning */
1195 bar_p = 0; /* prevent useless 'used before set' warning */
1196 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
1197 /*
1198 * Do various set up work per structure type. If it's a
1199 * visible staff, break and go do the rest of this loop.
1200 * Otherwise, "continue" on to the next structure.
1201 */
1202 switch (mainll_p->str) {
1203 case S_SSV:
1204 /* keep SSVs up to date; we need to know timeden */
1205 asgnssv(mainll_p->u.ssv_p);
1206 continue;
1207
1208 case S_CHHEAD:
1209 /* always remember preceding chord headcell */
1210 chhead_p = mainll_p->u.chhead_p;
1211 continue;
1212
1213 case S_BAR:
1214 /* always remember where the preceding bar was */
1215 bar_p = mainll_p->u.bar_p;
1216 continue;
1217
1218 case S_CLEFSIG:
1219 /*
1220 * The pseudo bar that's in a clefsig following a
1221 * scorefeed overrides the real bar at the end of the
1222 * previous score.
1223 */
1224 if (mainll_p->u.clefsig_p->bar_p != 0)
1225 bar_p = mainll_p->u.clefsig_p->bar_p;
1226 continue;
1227
1228 case S_STAFF:
1229 /* visible staff breaks out to do rest of the loop */
1230 if (mainll_p->u.staff_p->visible == YES)
1231 break;
1232 continue;
1233
1234 default:
1235 continue;
1236 }
1237
1238 /* get stepsize for this staff */
1239 stepsize = STEPSIZE * svpath(mainll_p->u.staff_p->staffno,
1240 STAFFSCALE)->staffscale;
1241
1242 /*
1243 * Loop through all the stuff on this staff.
1244 */
1245 for (stuff_p = mainll_p->u.staff_p->stuff_p; stuff_p != 0;
1246 stuff_p = stuff_p->next) {
1247 /*
1248 * Handle the special case of a fermata on a measure
1249 * rest. No matter what count the user requested,
1250 * we're going to center it above or below the measure
1251 * rest character. We also assume there is no "til"
1252 * clause.
1253 */
1254 if (string_is_sym(stuff_p->string, C_FERM, FONT_MUSIC) == YES ||
1255 string_is_sym(stuff_p->string, C_UFERM, FONT_MUSIC) == YES) {
1256
1257 if (setmrferm(mainll_p->u.staff_p, stuff_p)
1258 == YES)
1259 continue;
1260 /*
1261 * The fermata is not on a measure rest. Fall
1262 * through to handle like any normal stuff.
1263 */
1264 }
1265
1266 /*
1267 * Set c[AX] for the stuff.
1268 */
1269 if (stuff_p->gracebackup == 0) {
1270 /*
1271 * Use the c[INCHPERWHOLE] coordinate of the
1272 * chord or bar line that is at or before its
1273 * "start".
1274 */
1275 stuff_p->c[AX] = count2coord(
1276 stuff_p->start.count, bar_p, chhead_p,
1277 Score.timeden) +
1278 stuff_p->start.steps *
1279 STUFFSTEP(stuff_p);
1280 } else {
1281 /*
1282 * Since we have to back up by some number of
1283 * grace notes, we have to find a group to
1284 * associate the STUFF with. Then we can back
1285 * up from there.
1286 */
1287 v = 0; /* avoid 'used before set' warning */
1288 switch (svpath(mainll_p->u.staff_p->staffno,
1289 VSCHEME)->vscheme) {
1290 case V_1: /* 1 */
1291 v = 0; /* only one voice, use it */
1292 break;
1293 case V_2FREESTEM: /* 2f */
1294 case V_3FREESTEM: /* 3f */
1295 if (chkallspace(mainll_p, stuff_p, 0)
1296 == YES) {
1297 /* first voice all spaces */
1298 /* apply stuff to second */
1299 v = 1;
1300 break;
1301 } else if (chkallspace(mainll_p,
1302 stuff_p, 1) == YES) {
1303 /* second voice all spaces */
1304 /* apply stuff to first */
1305 v = 0;
1306 break;
1307 }
1308 /* FALL THROUGH;handle like V_2OPSTEM */
1309 case V_2OPSTEM: /* 2o */
1310 case V_3OPSTEM: /* 3o */
1311 v = stuff_p->place == PL_ABOVE ? 0 : 1;
1312 break;
1313 }
1314
1315 /* find closest note group in this voice */
1316 gs_p = closestgroup(stuff_p->start.count,
1317 mainll_p->u.staff_p->groups_p[v],
1318 Score.timeden);
1319
1320 /* back up right number of grace groups */
1321 for (n = 0; n < stuff_p->gracebackup; n++) {
1322 gs_p = gs_p->prev;
1323 if (gs_p == 0 || gs_p->grpvalue
1324 != GV_ZERO)
1325 l_ufatal(stuff_p->inputfile,
1326 stuff_p->inputlineno,
1327 "not enough grace groups to back up to for stuff");
1328 }
1329
1330 /*
1331 * Put the stuff at this grace group, except
1332 * that the steps offset must be applied.
1333 */
1334 stuff_p->c[AX] = gs_p->c[AX] +
1335 stuff_p->start.steps *
1336 STUFFSTEP(stuff_p);
1337 }
1338
1339 /*
1340 * If this stuff has a "til" clause, find where the
1341 * ending point is and set c[AE] to that. If this
1342 * stuff also has a string, and the string extends
1343 * beyond the point that the "til" clause asks for,
1344 * c[AE] will be changed later to agree with the string.
1345 */
1346 if (stuff_p->end.bars != 0 || stuff_p->end.count != 0) {
1347 /*
1348 * Init variables to the current position
1349 * (beginning of the stuff). If the stuff is
1350 * supposed to extend across one or more bar
1351 * lines, geteast() will alter them to the
1352 * correct values for the bar where the stuff
1353 * ends. It will blow away the 'til' clause in
1354 * certain multirest scenarios.
1355 */
1356 m2_p = mainll_p; /* this stuff's staff*/
1357 timeden2 = Score.timeden;
1358 chhead2_p = chhead_p;
1359 bar2_p = bar_p;
1360
1361 ret = geteast(stuff_p, m2_p, &timeden2,
1362 &chhead2_p, &bar2_p);
1363
1364 switch (ret) {
1365 case 1:
1366 /*
1367 * Set c[AE] for the stuff, using the
1368 * c[INCHPERWHOLE] coordinate of the
1369 * chord or bar line that precedes or
1370 * is at the end of it.
1371 */
1372 stuff_p->c[AE] = count2coord(
1373 stuff_p->end.count,
1374 bar2_p, chhead2_p, timeden2);
1375 break;
1376 case 2:
1377 /* end the stuff a little beyond the */
1378 /* barline at the start of the stuff */
1379 stuff_p->c[AE] = bar2_p->c[AX]
1380 + STUFFSTEP(stuff_p);
1381 break;
1382 case 3:
1383 /* no "til" clause anymore */
1384 /* set to 0 temporarily */
1385 stuff_p->c[AE] = 0;
1386 break;
1387 }
1388 /*
1389 * If there is still a "til" clause (it wasn't
1390 * blown away), make sure AE isn't left of AX.
1391 * Although the parse phase checks the bars and
1392 * counts for this, it could still happen here
1393 * if start.steps is too big. If it happens,
1394 * warn, and set AE to AX.
1395 */
1396 if (stuff_p->end.bars != 0 ||
1397 stuff_p->end.count != 0) {
1398 if (stuff_p->c[AE] < stuff_p->c[AX]) {
1399 l_warning(stuff_p->inputfile,
1400 stuff_p->inputlineno,
1401 "mark begins after 'til' position; moving 'til' position to the right");
1402 stuff_p->c[AE] = stuff_p->c[AX];
1403 }
1404 }
1405 } else {
1406 /* no "til" clause; set to 0 temporarily */
1407 stuff_p->c[AE] = 0;
1408 }
1409
1410 /*
1411 * Set c[AW] for all stuff types, and c[AE] for ones
1412 * that don't have a "til" clause. Reset c[AE] for
1413 * ones that have a "til" clause, if they have a string
1414 * that sticks out farther than that.
1415 */
1416 switch (stuff_p->stuff_type) {
1417 case ST_ROM:
1418 case ST_BOLD:
1419 case ST_ITAL:
1420 case ST_BOLDITAL:
1421 case ST_MUSSYM:
1422 case ST_PEDAL:
1423 case ST_OCTAVE:
1424 /*
1425 * These types (and only these) have a string.
1426 * (However, pedal continuations don't, so
1427 * treat them specially.) Set c[AW] such that
1428 * the first character will be centered at
1429 * c[AX].
1430 */
1431 if (stuff_p->string == 0) {
1432 /* must be a pedal continuation; */
1433 /* these have no width */
1434 stuff_p->c[AW] = stuff_p->c[AE] =
1435 stuff_p->c[AX];
1436 break;
1437 }
1438
1439 /* not a pedal continuation */
1440
1441 /*
1442 * If this is a chord with a grid, handle it
1443 * all in the subroutine.
1444 */
1445 if (stuff_p->modifier == TM_CHORD && trygrid(
1446 mainll_p, stuff_p) == YES) {
1447 break;
1448 }
1449
1450 leftwid = left_width(stuff_p->string);
1451 stuff_p->c[AW] = stuff_p->c[AX] - leftwid;
1452
1453 /* find the initial east of the string */
1454 streast = stuff_p->c[AW] +
1455 strwidth(stuff_p->string);
1456 /*
1457 * If the string would go beyond the right
1458 * margin, try to split it onto multiple lines,
1459 * and reset the string's east. Don't do this
1460 * for chord/analysis/figbass.
1461 */
1462 if (streast > PGWIDTH -
1463 eff_rightmargin(mainll_p) &&
1464 ! IS_CHORDLIKE(stuff_p->modifier)) {
1465 stuff_p->string = split_string(
1466 stuff_p->string, PGWIDTH -
1467 eff_rightmargin(mainll_p) -
1468 stuff_p->c[AW]);
1469 streast = stuff_p->c[AW] +
1470 strwidth(stuff_p->string);
1471 }
1472
1473 /*
1474 * If this east is beyond the east given by the
1475 * "til" clause (if any), use it for the AE.
1476 */
1477 if (streast > stuff_p->c[AE])
1478 stuff_p->c[AE] = streast;
1479
1480 break;
1481
1482 case ST_CRESC:
1483 case ST_DECRESC:
1484 case ST_PHRASE:
1485 case ST_TIESLUR: /* due to carry-in into ending */
1486 case ST_TABSLUR: /* due to carry-in into ending */
1487 case ST_BEND: /* due to carry-in into ending */
1488 /*
1489 * These types (and only these) have no string.
1490 * Set c[AW] the same as c[AX]. These always
1491 * have "til" clauses, so c[AE] is already set.
1492 * (Actually, c[AE] is not set for TIESLUR,
1493 * TABSLUR, or BEND, but no one uses it anyhow.)
1494 */
1495 stuff_p->c[AW] = stuff_p->c[AX];
1496 break;
1497
1498 case ST_MIDI:
1499 /* this file doesn't deal with MIDI at all */
1500 break;
1501
1502 default:
1503 pfatal("unknown stuff type %d",
1504 stuff_p->stuff_type);
1505 }
1506 }
1507 }
1508}
1509\f
1510/*
1511 * Name: count2coord()
1512 *
1513 * Abstract: Convert a count in a measure to the absolute horizontal coord.
1514 *
1515 * Returns: coordinate corresponding to the given count
1516 *
1517 * Description: This function, given a count number in a measure, and the
1518 * preceding bar line, chord head cell, and time signature
1519 * denominator, calculates and returns the absolute horizonal
1520 * coordinate of that place. In a measure, the preceding bar line
1521 * (or pseudo bar line, if this is the first measure of a score)
1522 * is regarded as count 0, and the following bar line is regarded
1523 * as count N + 1, where N is the numerator of the time signature.
1524 * Between any adjacent chords, or chord and bar line, time is
1525 * treated as proportional to distance.
1526 */
1527
1528static double
1529count2coord(count, bar_p, chhead_p, timeden)
1530
1531double count; /* count in measure */
1532struct BAR *bar_p; /* bar at start of measure (pseudobar if 1st in score)*/
1533struct CHHEAD *chhead_p;/* chord headcell for this measure */
1534int timeden; /* denominator of time signature in this measure */
1535
1536{
1537 struct CHORD *ch_p, *nch_p; /* point at CHORD structures */
1538 float frac; /* what fraction of a whole it starts at */
1539 float coord; /* the answer */
1540
1541
1542 if (count < 1) {
1543 /*
1544 * The stuff is before the first chord ("count 1"). So we
1545 * consider the preceding bar line to be count 0, and allocate
1546 * time proportionally.
1547 */
1548 coord = bar_p->c[AX] + (count / timeden) *
1549 bar_p->c[INCHPERWHOLE];
1550 } else {
1551 /*
1552 * Convert the "count" where this stuff begins to what fraction
1553 * of a whole it starts at.
1554 */
1555 frac = (count - 1) / timeden;
1556
1557 /*
1558 * In this loop, ch_p starts at the first chord and nch_p is
1559 * the next chord. They move forward in parallel. We get out
1560 * either when nch_p is 0 (ch_p is the last chord), or when
1561 * nch_p is beyond the place where our stuff goes (the stuff
1562 * goes at or following ch_p).
1563 */
1564 for (ch_p = chhead_p->ch_p, nch_p = ch_p->ch_p;
1565 nch_p != 0 && RAT2FLOAT(nch_p->starttime) <= frac;
1566 ch_p = nch_p, nch_p = nch_p->ch_p)
1567 ;
1568
1569 /*
1570 * Subtract to find how far (timewise) the stuff is after chord
1571 * ch_p. Then allocate space proportionally.
1572 */
1573 coord = ch_p->c[AX] + (frac - RAT2FLOAT(ch_p->starttime)) *
1574 ch_p->c[INCHPERWHOLE];
1575 }
1576
1577 return (coord);
1578}
1579\f
1580/*
1581 * Name: geteast()
1582 *
1583 * Abstract: Point variables at things relevant to the east end of a STUFF.
1584 *
1585 * Returns: 1 if count2coord() should be used to find AE of stuff
1586 * 2 if AE of stuff should be near *bar_p_p due to multirest
1587 * 3 if 'til' clause is being blown away due to multirest
1588 *
1589 * Description: This function is given pointers pertaining to a measure where
1590 * a STUFF begins. It searches forward to the end of the stuff,
1591 * according to the given number of measures. It sets *timeden2_p,
1592 * *chhead2_p_p, and *bar2_p_p to the values they should be for
1593 * the end of the stuff, if the return code is 1 (the usual case).
1594 * For 2 and 3, only *bar2_p_p is guaranteed to be meaningful.
1595 */
1596
1597static int
1598geteast(stuff_p, m2_p, timeden2_p, chhead2_p_p, bar2_p_p)
1599
1600struct STUFF *stuff_p; /* pointer to the stuff */
1601struct MAINLL *m2_p; /* starts at start of stuff, change to end */
1602short *timeden2_p; /* starts at start of stuff, change to end */
1603struct CHHEAD **chhead2_p_p; /* starts at start of stuff, change to end */
1604struct BAR **bar2_p_p; /* starts at start of stuff, change to end */
1605
1606{
1607 int blimit; /* number of bars to search forward past */
1608 int timenum; /* numerator of time signature */
1609 int b; /* count bar lines */
1610
1611
1612 blimit = stuff_p->end.bars; /* number of bars to cross */
1613
1614 /* if all within one bar, return right away */
1615 if (blimit == 0) {
1616 /* if starts and ends inside multirest, blow away 'til' clause*/
1617 if (m2_p->u.staff_p->groups_p[0]->basictime < -1) {
1618 stuff_p->end.count = 0;
1619 return (3);
1620 }
1621
1622 return (1); /* normal case; retain 'til' clause */
1623 }
1624
1625 timenum = Score.timeden; /* keep track of time sig numerator */
1626
1627 /*
1628 * The input parameters point at values that are for the beginning of
1629 * the stuff. Loop forward the requested number of bars to get to the
1630 * end of the stuff. While doing this, keep those variables updated.
1631 * By the end of this function, they will be correct for the end of
1632 * the stuff.
1633 */
1634 b = 0;
1635 /* if it starts at a multirest, account for that */
1636 if (m2_p->u.staff_p->groups_p[0]->basictime < -1) {
1637 /* if it ends inside the multirest, point at previous bar, */
1638 /* blow away 'til' clause, and get out */
1639 if (-(m2_p->u.staff_p->groups_p[0]->basictime) > blimit) {
1640 *bar2_p_p = m2_p->u.bar_p;
1641 stuff_p->end.bars = 0;
1642 stuff_p->end.count = 0;
1643 return (3);
1644 }
1645
1646 b = -1 - m2_p->u.staff_p->groups_p[0]->basictime;
1647 }
1648 for ( ; b < blimit; b++) {
1649 for (m2_p = m2_p->next; m2_p != 0 && m2_p->str != S_BAR;
1650 m2_p = m2_p->next) {
1651
1652 switch (m2_p->str) {
1653 case S_SSV:
1654 if (m2_p->u.ssv_p->used[TIME] == YES) {
1655 timenum = m2_p->u.ssv_p->timenum;
1656 *timeden2_p = m2_p->u.ssv_p->timeden;
1657 }
1658 break;
1659
1660 case S_STAFF:
1661 /* multirests count as multiple measures */
1662 if (m2_p->u.staff_p->staffno == 1 &&
1663 m2_p->u.staff_p->groups_p[0]->basictime < -1) {
1664
1665 /* add (multi - 1) to no. of bars */
1666 b -= 1 + m2_p->u.staff_p->
1667 groups_p[0]->basictime;
1668
1669 /*
1670 * If the stuff doesn't make it into
1671 * the last measure, or doesn't make it
1672 * to the last measure's bar line, make
1673 * it stop at the bar before multirest.
1674 */
1675 if (b > blimit || b == blimit &&
1676 stuff_p->end.count < timenum + 1) {
1677 return (2);
1678 }
1679
1680 /*
1681 * If it ends at the bar after the
1682 * multirest, move forward to that bar
1683 * and end the stuff there.
1684 */
1685 if (b == blimit) {
1686 while (m2_p->str != S_BAR)
1687 m2_p = m2_p->next;
1688 *bar2_p_p = m2_p->u.bar_p;
1689 return (2);
1690 }
1691 }
1692 break;
1693 }
1694 }
1695
1696 if (m2_p == 0)
1697 pfatal("'til' clause extends beyond end of the piece [geteast1]");
1698
1699 *bar2_p_p = m2_p->u.bar_p;
1700 }
1701
1702 /*
1703 * m2_p points at the bar line preceding or at the place where the
1704 * stuff ends. Continue forward to be pointing at the CHHEAD of that
1705 * measure and also do final variable updates.
1706 */
1707 for ( ; m2_p != 0 && m2_p->str != S_CHHEAD;
1708 m2_p = m2_p->next) {
1709
1710 switch (m2_p->str) {
1711 case S_SSV:
1712 if (m2_p->u.ssv_p->used[TIME] == YES)
1713 *timeden2_p = m2_p->u.ssv_p->timeden;
1714 break;
1715 case S_CLEFSIG:
1716 if (m2_p->u.clefsig_p->bar_p != 0)
1717 *bar2_p_p = m2_p->u.clefsig_p->bar_p;
1718 break;
1719 }
1720 }
1721
1722 if (m2_p == 0)
1723 pfatal("'til' clause extends beyond end of the piece [geteast2]");
1724
1725 /*
1726 * If the first staff in this measure has a multirest, return that fact
1727 * and have the stuff end at this bar line.
1728 */
1729 if (m2_p->next->u.staff_p->groups_p[0]->basictime < -1)
1730 return (2);
1731
1732 *chhead2_p_p = m2_p->u.chhead_p;
1733
1734 return (1); /* didn't end during a multirest */
1735}
1736\f
1737/*
1738 * Name: setmrferm()
1739 *
1740 * Abstract: Set absolute horizonal coords of a fermata on measure rest/rpt.
1741 *
1742 * Returns: YES or NO
1743 *
1744 * Description: This function is given a staff and a stuff for a fermata there.
1745 * It decides whether the fermata applies to a measure rest or a
1746 * measure repeat. If it does, it sets its coords to align with
1747 * the symbol and returns YES. Otherwise it returns NO.
1748 */
1749
1750static int
1751setmrferm(staff_p, stuff_p)
1752
1753struct STAFF *staff_p;
1754struct STUFF *stuff_p;
1755
1756{
1757 struct GRPSYL *gs_p; /* point at the relevant grpsyl list */
1758 float fermx; /* the center of the fermata */
1759 float fermwidth; /* width of the fermata */
1760 int font, size, code; /* of the fermata */
1761 char *s_p; /* point into the string holding the fermata */
1762
1763
1764 debug(32, "setmrferm file=%s line=%d", stuff_p->inputfile,
1765 stuff_p->inputlineno);
1766 /*
1767 * Who knows why the user would put a fermata between two staffs, but
1768 * if they did, treat it as normal stuff.
1769 */
1770 if (stuff_p->place == PL_BETWEEN)
1771 return (NO);
1772
1773 /*
1774 * Figure out which voice this fermata is meant to apply to. It could
1775 * be that one voice has a measure rest and the other doesn't. For
1776 * measure repeats, both would have it, so we wouldn't care which
1777 * voice, but we might as well fall through the same code. Point
1778 * at the first GRPSYL in that voice's list.
1779 */
1780 gs_p = 0; /* prevent useless 'used before set' warning */
1781 switch (svpath(staff_p->staffno, VSCHEME)->vscheme) {
1782 case V_1:
1783 /* only 1 voice, this must be it */
1784 gs_p = staff_p->groups_p[0];
1785 break;
1786
1787 case V_2OPSTEM:
1788 case V_3OPSTEM:
1789 /*
1790 * Technically we should attach the fermata to the voice it is
1791 * next to. But if that voice is all spaces, that wouldn't
1792 * make much sense. So fall through and handle the same as
1793 * the freestem cases.
1794 */
1795
1796 case V_2FREESTEM:
1797 case V_3FREESTEM:
1798 /* apply it to the nearest voice, unless it's all spaces */
1799 if (stuff_p->place == PL_ABOVE) {
1800 if ( ! hasspace(staff_p->groups_p[0], Zero, Score.time))
1801 gs_p = staff_p->groups_p[0];
1802 else
1803 gs_p = staff_p->groups_p[1];
1804 } else {
1805 if ( ! hasspace(staff_p->groups_p[1], Zero, Score.time))
1806 gs_p = staff_p->groups_p[1];
1807 else
1808 gs_p = staff_p->groups_p[0];
1809 }
1810 break;
1811 }
1812
1813 /*
1814 * If the relevant voice is not a measure rest or measure repeat, don't
1815 * do anything more. Just return and let the normal "stuff" code
1816 * handle this fermata.
1817 */
1818 if (gs_p->is_meas == NO)
1819 return (NO);
1820
1821 /*
1822 * This fermata is on a measure rest/repeat. We can't rely on the AX
1823 * of this; it's offset like a whole rest would be. We have to
1824 * average the AW and AE to know where the center should be.
1825 * If the user requested a stepsize offset, we will apply it to the
1826 * result, so in that case it won't really be centered after all.
1827 */
1828 fermx = (gs_p->c[AW] + gs_p->c[AE]) / 2 +
1829 stuff_p->start.steps * STEPSIZE;
1830
1831 /* find width of fermata */
1832 font = stuff_p->string[0];
1833 size = stuff_p->string[1];
1834 s_p = &stuff_p->string[2];
1835 code = next_str_char(&s_p, &font, &size);
1836 fermwidth = width(font, size, code);
1837
1838 /* set the absolute horizontal coords */
1839 stuff_p->c[AX] = fermx;
1840 stuff_p->c[AW] = fermx - fermwidth / 2;
1841 stuff_p->c[AE] = fermx + fermwidth / 2;
1842
1843 return (YES);
1844}
1845\f
1846/*
1847 * Name: trygrid()
1848 *
1849 * Abstract: Handle a chord STUFF if there are chord grids.
1850 *
1851 * Returns: YES if a grid will be printed with this chord, NO if not
1852 *
1853 * Description: If there are to be chord grids printed at the end of the song,
1854 * this function sets the "used" flag. If a grid should be
1855 * printed here (where the chord is used), it sets the coordinates
1856 * of this STUFF appropriately.
1857 */
1858
1859static int
1860trygrid(mainll_p, stuff_p)
1861
1862struct MAINLL *mainll_p; /* MLL struct for this chord stuff */
1863struct STUFF *stuff_p; /* the chord stuff */
1864
1865{
1866 int gridswhereused; /* YES or NO for this staff */
1867 struct GRID *grid_p; /* point to the grid definition */
1868 char *asciichord_p; /* point at ASCII version of chord */
1869 float geast, gwest; /* relative coords of the grid */
1870 float hstrw; /* half the width of the chord string */
1871
1872
1873 gridswhereused = svpath(mainll_p->u.staff_p->staffno,
1874 GRIDSWHEREUSED)->gridswhereused;
1875
1876 if (Score.gridsatend == NO && gridswhereused == NO) {
1877 return (NO);
1878 }
1879
1880 grid_p = findgrid(stuff_p->string);
1881
1882 /* if grid was never defined, warn and return no grid here */
1883 if (grid_p == 0) {
1884 asciichord_p = ascii_str(stuff_p->string, YES, NO, TM_CHORD);
1885 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1886 "no grid defined for chord %s", asciichord_p);
1887 return (NO);
1888 }
1889
1890 if (Score.gridsatend == YES) { /* grids print at end of song*/
1891 /* mark grid as used if it hasn't been, and keep count */
1892 if (grid_p->used == NO) {
1893 grid_p->used = YES;
1894 Atend_info.grids_used++;
1895 }
1896 }
1897
1898 /* if no grid is to be printed here, get out */
1899 if (gridswhereused == NO)
1900 return (NO);
1901
1902 /* we only need east & west here */
1903 gridsize(grid_p, stuff_p->all ? 0 : mainll_p->u.staff_p->staffno,
1904 (float *)0, (float *)0, &geast, &gwest);
1905 hstrw = strwidth(stuff_p->string) / 2.0;
1906
1907 /*
1908 * The stuff extends as far as necessary to contain both the string and
1909 * the grid. Unlike for other string stuffs, the string is centered at
1910 * this count. (So is the grid, if you ignore any "X fr" string on its
1911 * right side.) Note: "til" clauses are not allowed on chords.
1912 */
1913 stuff_p->c[AE] = stuff_p->c[AX] + MAX(geast, hstrw);
1914 stuff_p->c[AW] = stuff_p->c[AX] + MIN(gwest, -hstrw);
1915
1916 return (YES); /* grid gets printed here */
1917}
1918\f
1919/*
1920 * Name: tieslurstuff()
1921 *
1922 * Abstract: Create STUFF structures for all ties, slurs, and bends.
1923 *
1924 * Returns: void
1925 *
1926 * Description: This function puts ST_TIESLUR, ST_TABSLUR, and ST_BEND STUFF
1927 * structures in the linked lists. Unlike for the other stuff
1928 * types, the parser never does this. So up until now, there have
1929 * been none of these in the linked lists. More than one STUFF is
1930 * needed if there the tie/slur/bend is across a bar line into
1931 * endings, or across a scorefeed.
1932 */
1933
1934static void
1935tieslurstuff()
1936{
1937 struct MAINLL *mainll_p; /* point along main linked list */
1938 struct GRPSYL *gs_p; /* point at a group */
1939 int v; /* voice number, 0 or 1 */
1940 int n, k; /* loop variables */
1941
1942
1943 debug(16, "tieslurstuff");
1944 initstructs();
1945
1946 /*
1947 * Loop through main linked list, looking for visible STAFFs.
1948 */
1949 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
1950
1951 if (mainll_p->str == S_SSV) {
1952 /* keep SSVs up to date for benefit of l_warning */
1953 asgnssv(mainll_p->u.ssv_p);
1954 continue;
1955 }
1956
1957 if (mainll_p->str != S_STAFF ||
1958 mainll_p->u.staff_p->visible == NO)
1959 continue;
1960
1961 /*
1962 * Loop through all voices on this staff.
1963 */
1964 for (v = 0; v < MAXVOICES && mainll_p->u.staff_p->
1965 groups_p[v] != 0; v++) {
1966 /*
1967 * Loop through the groups in this voice. Ignore rests
1968 * and spaces.
1969 */
1970 for (gs_p = mainll_p->u.staff_p->groups_p[v];
1971 gs_p != 0; gs_p = gs_p->next) {
1972
1973 if (gs_p->grpcont != GC_NOTES)
1974 continue;
1975
1976 /*
1977 * For each note in this group, for each tie
1978 * and slur starting at it, call a function to
1979 * allocate a STUFF for it (more if into an
1980 * ending or scorefeed). However, do not do
1981 * this for ties on a tablature staff. They
1982 * are not to be printed.
1983 */
1984 for (n = 0; n < gs_p->nnotes; n++) {
1985 if (gs_p->notelist[n].tie == YES &&
1986 ! is_tab_staff(mainll_p
1987 ->u.staff_p->staffno))
1988 mktieslurstuff(mainll_p,
1989 gs_p, n, -1);
1990
1991 for (k = 0; k < gs_p->notelist[n].
1992 nslurto; k++) {
1993 mktieslurstuff(mainll_p,
1994 gs_p, n, k);
1995 }
1996 }
1997 }
1998 }
1999 }
2000}
2001\f
2002/*
2003 * Name: mktieslurstuff()
2004 *
2005 * Abstract: Create STUFF structure(s) for one tie/slur/bend.
2006 *
2007 * Returns: void
2008 *
2009 * Description: This function puts ST_TIESLUR, ST_TABSLUR, or ST_BEND STUFF
2010 * structure(s) in the linked list for one tie or slur curve.
2011 * Normally only one is needed, but if it crosses a scorefeed
2012 * two are needed, and if it crosses into a first ending, one is
2013 * needed for each following ending.
2014 */
2015
2016static void
2017mktieslurstuff(mllstaff_p, gs_p, n, s)
2018
2019struct MAINLL *mllstaff_p; /* MLL of staff where tie/slur/bend starts */
2020struct GRPSYL *gs_p; /* ptr to group where tie/slur/bend starts */
2021int n; /* index to note in notelist where it starts */
2022int s; /* index into slurtolist, or -1 for tie */
2023
2024{
2025 struct STUFF *stuff_p; /* point at a STUFF structure */
2026 struct STAFF *staff_p; /* point at staff of mllstaff */
2027 struct MAINLL *mll_p; /* point along MLL */
2028 struct MAINLL *mll2_p; /* another pointer along MLL */
2029 struct BAR *bar_p; /* point to a bar or pseudobar */
2030 struct MAINLL *ebmll_p; /* end bar MLL struct */
2031 int endingloc; /* ending location */
2032 int stufftype; /* which of the stuff types is it? */
2033
2034
2035 staff_p = mllstaff_p->u.staff_p;
2036
2037 if (s == -1) { /* tie */
2038 stufftype = ST_TIESLUR;
2039 } else if (gs_p->notelist[n].is_bend == YES) { /* bend */
2040 stufftype = ST_BEND;
2041 } else if (is_tab_staff(staff_p->staffno) || /* slur on tab or */
2042 is_tab_staff(staff_p->staffno + 1)) { /* tabnote staff */
2043 stufftype = ST_TABSLUR;
2044 } else { /* slur on other staff*/
2045 stufftype = ST_TIESLUR;
2046 }
2047
2048 /* allocate a STUFF structure for this tie/slur/bend */
2049 stuff_p = newSTUFF((char *)0, 0, SD_NONE, (double)0, (double)0, 0, 0,
2050 (double)0, stufftype, NO, PL_UNKNOWN, (char *)0, 0);
2051
2052 /* fill in additional items needed for tie/slur */
2053 stuff_p->vno = gs_p->vno;
2054 stuff_p->beggrp_p = gs_p;
2055 stuff_p->begnote_p = &gs_p->notelist[n];
2056 stuff_p->curveno = (short)s;
2057
2058 /* put the new STUFF into this staff's stuff list, at start of list */
2059 stuff_p->next = staff_p->stuff_p;
2060 staff_p->stuff_p = stuff_p;
2061
2062 /* if this is not the last group in measure, no more STUFFs needed */
2063 if (gs_p->next != 0)
2064 return;
2065
2066 /* if this is a slur to/from nowhere, no second piece needed */
2067 if (s >= 0 && (stufftype == ST_TABSLUR || stufftype == ST_TIESLUR) &&
2068 IS_NOWHERE(gs_p->notelist[n].slurtolist[s].octave))
2069 return;
2070
2071 /*
2072 * We might need more STUFF(s), either because of a scorefeed, or
2073 * because of endings. First check for the scorefeed case.
2074 */
2075 /* find bar line at end of measure */
2076 for (ebmll_p = mllstaff_p; ebmll_p != 0 && ebmll_p->str != S_BAR;
2077 ebmll_p = ebmll_p->next)
2078 ;
2079 if (ebmll_p == 0)
2080 pfatal("final measure has no bar line");
2081
2082 /* does a feed occur before next staff? */
2083 for (mll_p = ebmll_p; mll_p != 0 && mll_p->str != S_FEED &&
2084 mll_p->str != S_STAFF; mll_p = mll_p->next)
2085 ;
2086 if (mll_p == 0)
2087 return;
2088
2089 if (mll_p->str == S_FEED) {
2090 /* found a feed, so try to make the extra STUFF */
2091 stuff_p->carryout = YES;
2092 mkextrastuff(mll_p, stuff_p, gs_p, n, s, stufftype);
2093 }
2094
2095 /*
2096 * Find whether we need to check for endings. This is true when we are
2097 * at the start of a first ending. So endingloc has to be STARTITEM,
2098 * and the previous bar must not be in an ending. If we are at a FEED,
2099 * look at the pseudobar's endingloc, else look at the previous real
2100 * bar. In any case, search back from the real bar.
2101 */
2102 if (mll_p->str == S_FEED) {
2103 /*
2104 * Find the next CLEFSIG. Normally it's the next thing after
2105 * this FEED, but it's possible there are block(s) here and so
2106 * it will be after some later FEED.
2107 */
2108 while (mll_p != 0 && mll_p->str != S_CLEFSIG)
2109 mll_p = mll_p->next;
2110 if (mll_p == 0)
2111 return; /* there must not be any more music */
2112 bar_p = mll_p->u.clefsig_p->bar_p;
2113 } else {
2114 bar_p = ebmll_p->u.bar_p;
2115 }
2116 if (bar_p->endingloc != STARTITEM)
2117 return;
2118 for (mll2_p = ebmll_p->prev; mll2_p != 0 && mll2_p->str != S_BAR;
2119 mll2_p = mll2_p->prev)
2120 ;
2121 if (mll2_p != 0 && (mll2_p->u.bar_p->endingloc == STARTITEM ||
2122 mll2_p->u.bar_p->endingloc == INITEM))
2123 return;
2124
2125 /*
2126 * The curve was into a first ending. So we have to loop forward,
2127 * looking for the bar lines at the start of each ending, and try to
2128 * make another STUFF for the curve carrying into that ending.
2129 */
2130 for ( ; mll_p != 0; mll_p = mll_p->next) {
2131
2132 if (mll_p->str != S_BAR)
2133 continue;
2134
2135 /* see if a pseudo bar occurs before the next staff */
2136 for (mll2_p = mll_p; mll2_p != 0 && mll2_p->str != S_STAFF &&
2137 (mll2_p->str != S_CLEFSIG ||
2138 mll2_p->u.clefsig_p->bar_p == 0);
2139 mll2_p = mll2_p->next)
2140 ;
2141 if (mll2_p == 0 || mll2_p->str == S_STAFF) {
2142 /* normal case, no pseudobar */
2143 endingloc = mll_p->u.bar_p->endingloc;
2144 } else {
2145 /* found pseudobar; use it instead of normal bar */
2146 endingloc = mll2_p->u.clefsig_p->bar_p->endingloc;
2147 }
2148
2149 switch (endingloc) {
2150
2151
2152 case NOITEM:
2153 case ENDITEM:
2154 /* out of all endings, we're done */
2155 return;
2156
2157 case STARTITEM:
2158 /*
2159 * We are at a bar that begins another ending. Try to
2160 * find the matching staff in this measure.
2161 */
2162 mkextrastuff(mll_p, stuff_p, gs_p, n, s, stufftype);
2163 }
2164 }
2165}
2166\f
2167/*
2168 * Name: mkextrastuff()
2169 *
2170 * Abstract: Create STUFF extra structure(s) for one tie/slur/bend.
2171 *
2172 * Returns: void
2173 *
2174 * Description: This function puts ST_TIESLUR, ST_TABSLUR, or ST_BEND STUFF
2175 * structure(s) in the linked list for the ending piece of a tie,
2176 * slur, or bend that is broken across a scorefeed or into a
2177 * second or later ending.
2178 */
2179
2180static void
2181mkextrastuff(mll_p, origstuff_p, gs_p, n, s, stufftype)
2182
2183struct MAINLL *mll_p; /* starts before first staff in measure */
2184struct STUFF *origstuff_p; /* original STUFF for this curve */
2185struct GRPSYL *gs_p; /* GRPSYL where curve started */
2186int n; /* index to note in notelist where it starts */
2187int s; /* index into slurtolist, or -1 for tie */
2188int stufftype; /* which of the stuff types is it? */
2189
2190{
2191 struct STUFF *stuff_p; /* new stuff */
2192 struct GRPSYL *endgs_p; /* group where tie/slur/bend ends */
2193 int k; /* loop variable */
2194
2195
2196 /* find first staff */
2197 for ( ; mll_p != 0 && mll_p->str != S_STAFF;
2198 mll_p = mll_p->next)
2199 ;
2200
2201 /* find matching staff */
2202 for ( ; mll_p != 0 && mll_p->str == S_STAFF &&
2203 mll_p->u.staff_p->staffno !=
2204 gs_p->staffno; mll_p = mll_p->next)
2205 ;
2206 if (mll_p == 0)
2207 pfatal("last bar missing in main linked list [mkextrastuff]");
2208 if (mll_p->str != S_STAFF) /* number of staffs changed? */
2209 return;
2210
2211
2212 /* allocate a STUFF structure second half of tie/slur/bend */
2213 stuff_p = newSTUFF((char *)0, 0, SD_NONE, (double)0, (double)0, 0, 0,
2214 (double)0, stufftype, NO, PL_UNKNOWN, (char *)0, 0);
2215
2216 stuff_p->carryin = YES;
2217 stuff_p->costuff_p = origstuff_p;
2218
2219 /* fill in additional items needed for tie/slur */
2220 stuff_p->vno = gs_p->vno;
2221 endgs_p = mll_p->u.staff_p->groups_p[gs_p->vno - 1];
2222 stuff_p->beggrp_p = endgs_p; /* "beg" is really set to the end here*/
2223
2224 /* begnote_p must be pointed at the note where tie/slur ends; find it */
2225 for (k = 0; k < endgs_p->nnotes; k++) {
2226 if (s == -1) {
2227 /* tie; check for matching note */
2228 if (endgs_p->notelist[k].letter ==
2229 gs_p->notelist[n].letter
2230 && endgs_p->notelist[k].octave ==
2231 gs_p->notelist[n].octave)
2232 break;
2233 } else {
2234 /* slur/bend; check for note we're slurring/bending to*/
2235 if (endgs_p->notelist[k].letter ==
2236 gs_p->notelist[n].slurtolist[s].letter
2237 && endgs_p->notelist[k].octave ==
2238 gs_p->notelist[n].slurtolist[s].octave)
2239 break;
2240 }
2241 }
2242 if (k == endgs_p->nnotes) {
2243 l_warning(endgs_p->inputfile, endgs_p->inputlineno,
2244 "can't find note being tied, slurred, or bent to");
2245 FREE(stuff_p);
2246 return;
2247 }
2248
2249 stuff_p->begnote_p = &endgs_p->notelist[k]; /* end of tie/slur */
2250 stuff_p->curveno = (short)s; /* same as for the carryout stuff */
2251
2252 /* put the new STUFF into this staff's stuff list, at start of list */
2253 stuff_p->next = mll_p->u.staff_p->stuff_p;
2254 mll_p->u.staff_p->stuff_p = stuff_p;
2255}