1 /* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
2 /* All rights reserved */
6 * Description: This file contains functions for setting absolute
7 * horizontal coordinates.
15 static void barclefsigs P((void));
16 static int barwithssv P((struct MAINLL *mainll_p));
17 static void setclefsigwid P((struct MAINLL *mainll_p, struct CHHEAD *chhead_p));
18 static void abschunk P((struct MAINLL *mainll_p, struct MAINLL *end_p));
19 static void tryabs P((struct MAINLL *mainll_p, double scale, int *scores_p,
20 short measinscore[]));
21 static int endchunk P((struct MAINLL *mainll_p));
22 static double adjust_measwid4mrpt P((double oldmeaswid, struct CHORD *ch_p));
23 static void fillclefsig P((struct CLEFSIG *clefsig_p, struct MAINLL *feed_p));
24 static struct MAINLL *trymeasure P((struct MAINLL *mainll_p, double scale,
25 float *measwidth_p, float *adjust_p, int *ressv_p));
26 static void setabs P((struct MAINLL *start_p, int scores, short measinscore[]));
27 static void chkrestart P((struct MAINLL *start_p, struct MAINLL *end_p));
28 static void setabsscore P((struct MAINLL *start_p, struct MAINLL *end_p));
29 static void setabschord P((struct CHORD *ch_p, double nomx));
30 static double effwidth P((struct CHORD *ch_p));
31 static double bardiff P((struct MAINLL *mainll_p, struct MAINLL *end_p));
32 static void fixfullmeas P((struct CHORD *ch_p, double x));
33 static void restore_grpsyl_west P((void));
34 static void setipw P((void));
35 static void setipwgrpsyl P((struct MAINLL *mainll_p, struct GRPSYL *gs_p));
36 static void setipwchord P((struct MAINLL *mainll_p));
37 static void fixendings P((void));
38 static void fixreh P((void));
39 static void clrinhprint P((void));
40 static int hidestaffs P((struct MAINLL *mainll_p, struct MAINLL *ml2_p));
41 static int silent P((struct MAINLL *mainll_p, struct MAINLL *ml2_p, int s,
43 static int getmultinum P((struct MAINLL *mll_p));
46 * Depending on which type of clefsig, get its full width, or its effective
47 * width. The latter is for user requested ones, which may overlap notes.
49 #define EFF_WIDCLEFSIG(clefsig_p) \
50 ((clefsig_p)->clefsize == DFLT_SIZE ? width_clefsig(clefsig_p) : \
51 (clefsig_p)->effwidth)
54 * Define the padding after a clefsig. It's greater when there's a pseudobar,
55 * because we need to allow room for carry-in ties/slurs.
57 #define CSP(clefsig_p) (((clefsig_p)->bar_p == 0 ? 2.0 : 9.0) * STDPAD)
62 * Abstract: Set absolute horizontal coordinates of everything.
66 * Description: This function inserts the initial FEED of the piece. Then, for
67 * each section of the piece delimited by FEEDs (initial one and
68 * user-requested ones), it breaks it into the necessary number
69 * of scores (inserting more FEEDs), and sets all the horizontal
70 * absolute coordinates. Finally, it does some fix-up work.
77 struct MAINLL *mainll_p; /* point at any MAINLL member */
78 struct MAINLL *ml2_p; /* point at another MAINLL member */
79 struct MAINLL *mainfeed_p; /* point at MAINLL containing a FEED */
80 struct MAINLL *end_p; /* point to end of a chunk of MAINLL */
81 int gotbar; /* found a bar in this chunk */
85 ml2_p = 0; /* prevent useless 'used before set' warning */
88 * The parse phase put any user-requested score feeds in the main
89 * linked list. We must now insert a FEED before the first measure,
90 * unless the user already requested one there (unlikely!). Later
91 * we'll add more as needed.
93 for (mainll_p = Mainllhc_p;
94 mainll_p != 0 && mainll_p->str == S_SSV;
95 mainll_p = mainll_p->next)
96 ; /* skip by all initial SSVs */
99 pfatal("main linked list has nothing but SSVs");
101 if (mainll_p->str != S_FEED) {
102 mainfeed_p = newMAINLLstruct(S_FEED, 0);
103 insertMAINLL(mainfeed_p, mainll_p->prev);
106 /* whenever a CLEFSIG is needed after a bar line, put one there */
110 * Find each section of the main linked list, delimited by FEEDs.
111 * For each such section, call abschunk() to set the absolute
112 * horizontal coords for things in that chunk. At the end of each
113 * chunk, back up to avoid including SSVs/PRHEADs/LINEs/CURVEs which
114 * might follow the last measure of the chunk. If a chunk contains no
115 * bar lines (like if there was a useless scorefeed at the end),
116 * don't call abschunk().
118 /* skip anything before first FEED first */
119 for (mainll_p = Mainllhc_p; mainll_p->str != S_FEED;
120 mainll_p = mainll_p->next)
124 for (end_p = mainll_p->next;
125 end_p != 0 && end_p->str != S_FEED;
126 ml2_p = end_p, end_p = end_p->next) {
128 if (end_p->str == S_BAR)
134 * If end_p is 0, this must be the end of the MLL, and
135 * there was a final feed after all the music data.
136 * There is no need to process this chunk.
141 * This chunk must contain a BLOCKHEAD. There is no
142 * need to process it. Set the absolute horizontal
143 * coords. Then point mainll_p at the FEED at the end
144 * of the chunk, and go to the next loop.
146 mainll_p->u.feed_p->c[AW] = eff_leftmargin(mainll_p);
147 mainll_p->u.feed_p->c[AE] = PGWIDTH -
148 eff_rightmargin(end_p);
149 mainll_p->u.feed_p->c[AX] = (mainll_p->u.feed_p->c[AW]
150 + mainll_p->u.feed_p->c[AE]) / 2.0;
155 while (ml2_p->str == S_SSV || ml2_p->str == S_PRHEAD ||
156 ml2_p->str == S_LINE || ml2_p->str == S_CURVE)
158 abschunk(mainll_p, ml2_p->next);
164 /* restore west boundaries of GRPSYLs that have associated clefs */
165 restore_grpsyl_west();
167 /* set inches per whole ( c[INCHPERWHOLE] ) in the relevant structs */
170 /* move endings that start at end of score to the next score */
173 /* move rehearsal marks at end of a score to the next score */
176 /* clear the inhibitprint flag on tablature staffs when appropriate */
181 * Name: barclefsigs()
183 * Abstract: Put a CLEFSIG after each bar line that requires one.
187 * Description: This function loops through the main linked list, applying
188 * SSVs as it goes. Whenever an SSV changes clef, key, or time,
189 * it inserts a CLEFSIG into the list to show what will need to
190 * be printed at that point. It also inserts one after any bar
198 struct MAINLL *mainll_p; /* point at items in main linked list*/
199 struct MAINLL *maincs_p; /* point at MAINLL with CLEFSIG */
200 struct MAINLL *mll_p; /* point along MLL */
201 struct CLEFSIG *clefsig_p; /* point at CLEFSIG being filled in */
202 struct BAR *bar_p; /* point at the bar */
203 struct CHHEAD *chhead_p; /* point at the latest CHHEAD seen */
204 struct TIMEDSSV *tssv_p; /* point along timed SSV list */
205 struct GRPSYL *gs_p; /* point at a group */
206 int oldstaffs; /* no. of staffs before SSVs */
207 int oldvis[MAXSTAFFS + 1]; /* visibility of staffs before SSVs */
208 int oldclef[MAXSTAFFS + 1]; /* clefs before SSVs */
209 int newclef[MAXSTAFFS + 1]; /* clefs after SSVs */
210 int premidclef[MAXSTAFFS + 1]; /* clefs before applying midmeas SSVs*/
211 int oldkey[MAXSTAFFS + 1]; /* effective keys before SSVs */
212 int newkey[MAXSTAFFS + 1]; /* effective keys after SSVs */
213 int oldnorm[MAXSTAFFS + 1]; /* is staff "normal" (5 line, nontab)?*/
214 int newnorm[MAXSTAFFS + 1]; /* is staff "normal" (5 line, nontab)?*/
215 char oldtimerep[MAXTSLEN]; /* time sig before SSVs */
216 int oldclefsequal, oldkeysequal;/* were they equal on all staffs? */
217 int newclefsequal, newkeysequal;/* are they equal on all staffs? */
218 int gottimedssv; /* were there any timed SSVs? */
219 int vidx; /* voice index */
220 int lastclef; /* last clef printed */
221 RATIONAL offset; /* offset of a group in a measure */
222 RATIONAL lastclefoffset; /* offset of last midmeasure clef */
223 int timechg; /* did they change time sig info? */
224 int change; /* did they change clefs/keys/time? */
225 register int s; /* staff number */
228 debug(16, "barclefsigs");
229 initstructs(); /* clean out old SSV info */
231 /* apply any SSVs that come before the first measure */
232 mainll_p = Mainllhc_p;
233 while (mainll_p != 0 && mainll_p->str == S_SSV) {
234 asgnssv(mainll_p->u.ssv_p);
235 mainll_p = mainll_p->next;
238 chhead_p = 0; /* keep lint happy; will be set before used */
241 * Loop once for each bar line in the piece that has SSV(s) after it,
242 * or is a RESTART. Whenever this occurs, insert a CLEFSIG after them
243 * if required. RESTART always requires it.
247 * Find the next bar that is either followed by an SSV or has
248 * timed SSVs for the preceding measure or is a restart. These
249 * are the cases where a CLEFSIG may be needed. If we hit the
250 * end of the MLL, break out.
252 while (mainll_p != 0 && ! (mainll_p->str == S_BAR &&
253 (barwithssv(mainll_p) == YES ||
254 mainll_p->u.bar_p->timedssv_p != 0 ||
255 mainll_p->u.bar_p->bartype == RESTART))) {
256 switch (mainll_p->str) {
258 /* remember the last chhead */
259 chhead_p = mainll_p->u.chhead_p;
263 asgnssv(mainll_p->u.ssv_p);
266 mainll_p = mainll_p->next;
271 bar_p = mainll_p->u.bar_p;
274 * If there were timed SSVs in the measure just ended, we need
275 * to make sure that any clef changes requested actually got
276 * printed before some GRPSYL. If the clef was changed on one
277 * staff by <<score clef = whatever>>, some other staff may be
278 * affected and yet not have a GRPSYL after that point before
279 * which the clef can be printed. In that case, we want to
280 * generate a CLEFSIG at this bar line, to print it.
282 tssv_p = bar_p->timedssv_p;
283 gottimedssv = tssv_p != 0; /* remember if we had any */
285 /* get clef state before the timed SSVs */
286 for (s = 1; s <= Score.staffs; s++) {
287 premidclef[s] = svpath(s, CLEF)->clef;
289 /* assign the timed SSVs */
290 for ( ; tssv_p != 0; tssv_p = tssv_p->next) {
291 asgnssv(&tssv_p->ssv);
296 * Save the current number of staffs, whether they are visible,
297 * and all clefs and effective keys in case the SSVs coming
298 * up will change some of these things. Also, save the timesig
299 * info so we can check if it changed (it is settable only in
301 * Set oldnorm according to whether the staff is "normal",
302 * capable of having a clef or key sig.
303 * Set oldclefsequal and oldkeysequal according to whether all
304 * staffs have the same values for clef and key.
306 oldclefsequal = oldkeysequal = YES;
307 for (s = 1; s <= Score.staffs; s++) {
308 oldvis[s] = svpath(s, VISIBLE)->visible;
309 oldclef[s] = svpath(s, CLEF)->clef;
310 oldkey[s] = eff_key(s);
311 oldnorm[s] = svpath(s, STAFFLINES)->stafflines == 5 &&
312 svpath(s, STAFFLINES)->printclef == YES &&
313 ! is_tab_staff(s) ? YES : NO;
314 if (s > 1 && oldclef[s - 1] != oldclef[s])
316 if (s > 1 && oldkey[s - 1] != oldkey[s])
319 oldstaffs = Score.staffs;
320 strcpy(oldtimerep, Score.timerep);
322 /* see if clefs need printing due to timed SSVs */
324 /* check this on every staff */
325 for (s = 1; s <= Score.staffs; s++) {
326 /* find this staff's MLL structure */
327 for (mll_p = mainll_p; mll_p->str != S_STAFF ||
328 mll_p->u.staff_p->staffno != s;
329 mll_p = mll_p->prev) {
332 /* don't force clefsig for an invisible staff*/
333 if (mll_p->u.staff_p->visible == NO) {
337 * Find last clef that was printed for this
338 * measure. Start with the value of the clef
339 * at the previous bar (before any midmeasure
340 * clefs). Then update with the ones that were
341 * printed midmeasure, until we have the last.
343 lastclef = premidclef[s];
344 lastclefoffset = rneg(One);
345 for (vidx = 0; vidx < MAXVOICES; vidx++) {
346 /* look down this voice */
348 for (gs_p = mll_p->u.staff_p->groups_p[
349 vidx]; gs_p != 0; gs_p = gs_p->next) {
350 if (gs_p->clef != NOCLEF &&
351 GT(offset, lastclefoffset)) {
352 lastclef = gs_p->clef;
353 lastclefoffset = offset;
355 offset = radd(offset,
360 * Set the oldclef to the last one printed.
361 * Then later code will create a CLEFSIG, if
364 oldclef[s] = lastclef;
369 * Loop through this set of SSV(s), applying them. If we hit
370 * the end of the main linked list, break out. We don't want
371 * to put a CLEFSIG after the last bar line, regardless of
372 * whether it changed anything.
374 mainll_p = mainll_p->next;
375 while (mainll_p != 0 && mainll_p->str == S_SSV) {
376 asgnssv(mainll_p->u.ssv_p);
377 mainll_p = mainll_p->next;
379 /* Retain mainll_p for later; loop onwards using mll_p. Need */
380 /* to keep looking for SSVs in case there is a block here. */
382 while (mll_p != 0 && (mll_p->str == S_SSV ||
383 mll_p->str == S_FEED ||
384 mll_p->str == S_BLOCKHEAD)) {
385 if (mll_p->str == S_SSV) {
386 asgnssv(mll_p->u.ssv_p);
395 * Get the new clefs and effective keys.
396 * Again, find out if the clefs and keys are equal on all
399 newclefsequal = newkeysequal = YES;
400 for (s = 1; s <= Score.staffs; s++) {
401 newclef[s] = svpath(s, CLEF)->clef;
402 newkey[s] = eff_key(s);
403 newnorm[s] = svpath(s, STAFFLINES)->stafflines == 5 &&
404 svpath(s, STAFFLINES)->printclef == YES &&
405 ! is_tab_staff(s) ? YES : NO;
406 if (s > 1 && newclef[s - 1] != newclef[s])
408 if (s > 1 && newkey[s - 1] != newkey[s])
412 /* first check if any time sig info changed */
413 if (strcmp(Score.timerep, oldtimerep) != 0)
419 * If the bar was a restart, we treat it as if it were at the
420 * start of a score. That is, we always print the clefs and
421 * key signatures. The clefs are full size, and no naturals
422 * are printed. Print the time signature only if it changed.
424 if (bar_p->bartype == RESTART) {
426 * We always require a CLEFSIG. Allocate one and put
427 * it between where we are now and the preceding
430 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
431 insertMAINLL(maincs_p, mainll_p->prev);
432 clefsig_p = maincs_p->u.clefsig_p;
434 clefsig_p->clefsize = DFLT_SIZE; /* full size */
435 clefsig_p->multinum = getmultinum(maincs_p);
438 * Note: If the number of staffs is changing here, the
439 * following might not be right. But it doesn't
440 * matter, because in that case this CLEFSIG will be
441 * thrown away later anyway.
443 for (s = 1; s <= oldstaffs; s++) {
444 /* draw nothing if this staff is not "normal" */
445 if (oldnorm[s] == NO || newnorm[s] == NO)
447 clefsig_p->prclef[s] = YES;
448 clefsig_p->sharps[s] = newkey[s];
451 /* print the time signature if it changed */
452 clefsig_p->prtimesig = timechg;
458 * When the number of staffs changes, special rules apply.
459 * Handle this situation and continue.
461 if (oldstaffs != Score.staffs) {
463 * Identify the cases where no clefsig is needed, and
464 * continue. This is when time didn't change, and no
465 * clefs or keys are to be printed. Clefs are to be
466 * printed only when all the old staffs had the same
467 * clef, all the new ones had the same clef, and the
468 * old and new clefs are different. The analogous rule
469 * holds for keys. This is because, when the number of
470 * staffs changes, we can't really tell which old staff
471 * corresponds to which new staff (if any), so it's
472 * silly to print a clef or key change on any.
475 (oldclefsequal == NO ||
476 newclefsequal == NO ||
477 oldclef[1] == newclef[1]) &&
478 (oldkeysequal == NO ||
479 newkeysequal == NO ||
480 oldkey[1] == newkey[1])) {
481 /* no CLEFSIG needed here */
486 * Something changed that requires a CLEFSIG. Allocate
487 * one and put it between where we are now and the
488 * preceding structure, the last SSV we applied.
490 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
491 insertMAINLL(maincs_p, mainll_p->prev);
492 clefsig_p = maincs_p->u.clefsig_p;
494 /* any clefs to be printed should be small size */
495 clefsig_p->clefsize = SMALLSIZE;
496 clefsig_p->multinum = getmultinum(maincs_p);
499 * Since the number of staffs is changing, there will
500 * be a scorefeed here, and this CLEFSIG will be at the
501 * end of the first score. Every old staff will have
502 * the same info printed by the CLEFSIG, except that
503 * clef and key never exist on "abnormal" staffs. Check
504 * against staff 1 since we know that has to exist on
505 * both sides. It doesn't hurt to mark even invisible
508 for (s = 1; s <= oldstaffs; s++) {
510 /* draw nothing if this staff is not "normal" */
511 if (oldnorm[s] == NO || newnorm[s] == NO)
514 * Draw the new clef if the clefs on each score
515 * are consistent and they changed.
517 if (oldclefsequal && newclefsequal &&
518 oldclef[1] != newclef[1])
519 clefsig_p->prclef[s] = YES;
522 * Draw the new key if the keys on each score
523 * are consistent and they changed. See below
524 * for a more detailed explanation.
526 if (oldkeysequal && newkeysequal &&
527 oldkey[1] != newkey[1]) {
528 clefsig_p->sharps[s] = newkey[1];
530 if (newkey[1] == 0) {
531 clefsig_p->naturals[s] =
533 } else if (svpath(s, CANCELKEY)->
535 if (oldkey[1] * newkey[1] < 0) {
536 /* 1 has #s, 1 has &s */
537 clefsig_p->naturals[s] =
539 } else if (abs(oldkey[1]) >
541 /* new has fewer accs*/
542 clefsig_p->naturals[s] =
543 oldkey[1] - newkey[1];
549 /* print the time signature if it changed */
551 clefsig_p->prtimesig = YES;
553 /* set clefsig's effective width */
554 setclefsigwid(maincs_p, chhead_p);
562 /* see if anything else requiring a CLEFSIG changed */
563 for (s = 1; s <= oldstaffs; s++) {
564 if (oldvis[s] == NO ||
565 svpath(s, VISIBLE)->visible == NO)
567 if (oldclef[s] != newclef[s])
569 if (oldkey[s] != newkey[s])
572 break; /* don't waste any more time looping */
575 continue; /* no visible time, key, clef changed*/
578 * If we get here, it means either the clef, effective key, or
579 * time changed on some visible staff. Allocate a CLEFSIG and
580 * put it between where we are now and the preceding structure,
581 * which is the last SSV we applied.
583 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
584 insertMAINLL(maincs_p, mainll_p->prev);
585 clefsig_p = maincs_p->u.clefsig_p;
587 /* any clefs to be printed should be small size */
588 clefsig_p->clefsize = SMALLSIZE;
589 clefsig_p->multinum = getmultinum(maincs_p);
592 * Loop through the staffs, marking in the CLEFSIG what should
595 for (s = 1; s <= Score.staffs; s++) {
596 /* draw nothing if this staff is invisible */
600 /* draw nothing if this staff is not "normal" */
601 if (oldnorm[s] == NO || newnorm[s] == NO)
604 /* draw the new clef if the clef changed */
605 if (oldclef[s] != newclef[s])
606 clefsig_p->prclef[s] = YES;
609 * If the effective key changed, draw the new key
610 * signature. But if the new key has 0 sharps, we
611 * should draw naturals in the shape of the old key
612 * signature. And if cancelkey is set, and a sharp key
613 * is changing to a flat key or vice versa, or the
614 * number of sharps or flats is being reduced, we need
615 * enough naturals to cancel the ones being removed.
617 if (oldkey[s] != newkey[s]) {
618 clefsig_p->sharps[s] = newkey[s];
619 if (newkey[s] == 0) {
620 clefsig_p->naturals[s] = oldkey[s];
621 } else if (svpath(s, CANCELKEY)->
623 if (oldkey[s] * newkey[s] < 0) {
624 /* 1 has sharps, 1 has flats */
625 clefsig_p->naturals[s] =
627 } else if (abs(oldkey[s]) >
629 /* new has fewer accidentals */
630 clefsig_p->naturals[s] =
631 oldkey[s] - newkey[s];
638 * Finally, print the time signature if it changed.
641 clefsig_p->prtimesig = YES;
643 /* set clefsig's effective width, and widestclef */
644 setclefsigwid(maincs_p, chhead_p);
651 * Abstract: Is this bar followed by SSV(s), ignoring FEEDs and BLOCKHEADs?
655 * Description: This function is called with the MLL structure for a BAR.
656 * Ignoring the possible presence of FEEDs and BLOCKHEADs, return
657 * YES if the next structure is an SSV.
663 struct MAINLL *mainll_p; /* for the BAR */
666 struct MAINLL *mll_p; /* loop after the BAR */
669 for (mll_p = mainll_p->next; mll_p != 0; mll_p = mll_p->next) {
670 switch (mll_p->str) {
675 break; /* ignore these, keep looking */
681 return (NO); /* hit end of MLL */
685 * Name: setclefsigwid()
687 * Abstract: Set effective width and widest clef of a user requested clefsig.
691 * Description: This function is called with a user-requested clefsig. If it
692 * contains clefs, they should be printed before the bar line. If
693 * we are lucky, part or all of the clef's widths can overlap notes
694 * on other staffs. The effective width is the full width minus
695 * the amount that can overlap. This function sets the effective
696 * width of the clefsig, and the widest clef that it contains. We
697 * need to do this now, because we need to use the pseudo absolute
698 * coords set by relxchord() before they are overwritten later in
703 setclefsigwid(mainll_p, chhead_p)
705 struct MAINLL *mainll_p; /* point at the given clefsig's MLL struct */
706 struct CHHEAD *chhead_p; /* point at the preceding chhead */
709 struct MAINLL *m2_p; /* another pointer down the MLL */
710 struct CLEFSIG *clefsig_p; /* point at a clefsig */
711 struct CHORD *ch_p; /* point at a chord */
712 struct STAFF *staff_p; /* point at a staff */
713 struct GRPSYL *gs_p; /* point at a group in a voice */
714 struct GRPSYL *gs2_p; /* point at a group in a chord */
715 float lasteast; /* phony AE of last chord in measure */
716 float size; /* to be used for clef */
717 float clefspace; /* space needed for printing clefs */
718 float clefwid; /* width of a clef */
719 float widestclef; /* width of the widest to be printed */
720 float staffscale; /* scale for a staff */
721 float gap; /* between last group & last chord */
722 int staffno; /* staff number, 1 to MAXSTAFFS */
723 int clef; /* clef type */
724 int v; /* voice number, 0 to 2 */
727 debug(16, "setclefsigwid");
729 clefsig_p = mainll_p->u.clefsig_p; /* convenient pointer */
732 * Although relxchord() overlaps chords in various ways, it does not
733 * overlap the last chord in the measure with anything following.
734 * And it sets phony absolute coordinates for each chord, based on
735 * pretending that everything is packed as tight as possible. So, as
736 * the rightmost coord of all groups, we can use the AE of the last
737 * chord of the measure just ended.
739 for (ch_p = chhead_p->ch_p; ch_p->ch_p != 0; ch_p = ch_p->ch_p)
741 lasteast = ch_p->c[AE];
744 * Init the amount of space needed for clefs to be printed. We start
745 * at zero, and whenever a clef is to be printed, we find out how much
746 * of it can't be overlapped; and clefspace keeps track of the maximum
747 * of these for all staffs.
751 widestclef = 0.0; /* max width of any clef to be printed */
753 size = 3.0/4.0 * DFLT_SIZE; /* small size clefs */
756 * Loop backwards through the preceding measure, looking for visible
759 for (m2_p = mainll_p; m2_p->str != S_CHHEAD; m2_p = m2_p->prev) {
761 if (m2_p->str != S_STAFF || m2_p->u.staff_p->visible == NO)
764 staff_p = m2_p->u.staff_p;
765 staffno = staff_p->staffno;
767 /* if no clef, it doesn't need any space */
768 if (clefsig_p->prclef[staffno] == NO)
771 /* find width of this clef, including padding */
772 clef = svpath(staffno, CLEF)->clef;
773 staffscale = svpath(staffno, STAFFSCALE)->staffscale;
774 clefwid = (clefwidth(clef, YES) + CLEFPAD) * staffscale;
776 /* remember biggest clef width */
777 if (clefwid > widestclef)
778 widestclef = clefwid;
780 /* loop through all voices on this staff */
781 for (v = 0; v < MAXVOICES; v++) {
783 /* find last group in this voice */
784 gs_p = staff_p->groups_p[v];
787 for ( ; gs_p->next != 0; gs_p = gs_p->next)
791 * Find out what chord this group belongs to, by
792 * searching down the GRPSYL list hanging off each
793 * chord in this measure.
795 for (ch_p = chhead_p->ch_p; ch_p != 0;
797 for (gs2_p = ch_p->gs_p; gs2_p != 0;
798 gs2_p = gs2_p->gs_p) {
799 /* if found, or after the right staff*/
800 if (gs2_p == gs_p || gs2_p->staffno >
806 * If we found it, find the gap between this
807 * group's AE and the last chord's. If the
808 * amount of the clef's width that does not fit
809 * in that gap is the greatest so far, save it.
813 (ch_p->c[AX] + gs_p->c[RE]);
815 if (clefwid - gap > clefspace)
816 clefspace = clefwid - gap;
818 break; /* look no more */
821 } /* loop through voices on a staff */
822 } /* loop through staffs */
824 clefsig_p->widestclef = widestclef;
826 /* (effective width) = (real width) - (what can overlap) */
827 clefsig_p->effwidth = width_clefsig(clefsig_p) -
828 (widestclef - clefspace);
834 * Abstract: Set the absolute horz. coords of everything in one chunk.
838 * Description: This function is given a chunk of the piece, which is
839 * delimited by FEEDs. It estimates how many inches should
840 * be allocated to each whole note of time. Then it calls
841 * tryabs() repeatedly, trying to find a scale factor that
842 * will avoid having the last score be too empty. Finally,
843 * it calls setabs() to set the absolute horizontal coordinates
844 * of everything in the chunk.
848 abschunk(start_p, end_p)
850 struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
851 struct MAINLL *end_p; /* points after last struct in chunk (or 0) */
854 float totwidth; /* total minimal width of this chunk */
855 float totpseudodur; /* total pseudodur of measures in this chunk */
856 struct MAINLL *mainll_p;/* point at items in main linked list*/
857 struct CHORD *ch_p; /* point at a chord */
858 short *measinscore; /* malloc'ed array; bars in each score */
859 float packfact; /* as it was at the start of this score */
860 float lowscale; /* small guess at inches per whole */
861 float highscale; /* large guess at inches per whole */
862 float midscale; /* average of low and high scale */
863 float measwidth; /* width of a measure */
864 int numbars; /* number of measures in this chunk */
865 int scores; /* number of scores needed for this chunk */
866 int reqscores; /* the number of score required */
867 int trial; /* trial number for getting correct scale */
870 debug(16, "abschunk file=%s line=%d", start_p->inputfile,
871 start_p->inputlineno);
874 * For our first estimate of how wide to make everything, we need to
875 * add up the total minimal width and total elapsed time.
877 /* must apply all SSVs from start, to get the right time sig */
878 initstructs(); /* clean out old SSV info */
879 for (mainll_p = Mainllhc_p; mainll_p != start_p;
880 mainll_p = mainll_p->next) {
881 if (mainll_p->str == S_SSV)
882 asgnssv(mainll_p->u.ssv_p);
885 packfact = Score.packfact; /* use current value (start of score) */
886 totwidth = 0; /* start totals at 0 */
890 /* loop through chunk, adding up width and time */
891 for ( ; mainll_p != end_p; mainll_p = mainll_p->next) {
893 switch (mainll_p->str) {
895 /* assign to keep time sig accurate */
896 asgnssv(mainll_p->u.ssv_p);
901 * Add in the minimum widths of all chords in the
902 * measure, and add up the pseudoduration. There are
903 * special things done for mrpt: 1) if all staff(s)
904 * have mrpt, we don't want them to "deserve" as much
905 * space as an mr, so reduce their pseudodur; 2) the
906 * minimum width of the measure must be made wide
907 * enough to contain the symbol. Also, allow room
908 * for any midmeasure clefs. (This will happen
909 * automatically, because the group boundaries still
910 * include their preceding midmeasure clefs at this
914 ch_p = mainll_p->u.chhead_p->ch_p;
915 if (ABSDIFF(ch_p->width, TEMPMRPTWIDTH) < 0.001) {
916 /* the 0.001 is to allow for roundoff error */
917 ch_p->pseudodur *= 0.5;
919 for ( ; ch_p != 0; ch_p = ch_p->ch_p) {
920 measwidth += ch_p->width;
921 /* only count time if there is a real width */
922 /* (nonspace, or "us", or padded "s") */
923 if (ch_p->width != 0)
924 totpseudodur += ch_p->pseudodur;
926 /* add this measure into the total */
927 totwidth += adjust_measwid4mrpt(measwidth,
928 mainll_p->u.chhead_p->ch_p);
932 /* width of clef/key/time to print when changing */
933 totwidth += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p) +
934 CSP(mainll_p->u.clefsig_p);
938 /* add width of bar line, and incr no. of bars */
939 totwidth += width_barline(mainll_p->u.bar_p);
946 * Allocate the measinscore array. We need an element for each score
947 * that this chunk will be broken up into. We don't yet know how
948 * many that will be. So allocate enough for the worst case, where
949 * each measure is so wide that it has to go on a separate score.
951 MALLOCA(short, measinscore, numbars + 1);
954 * Our first trial is to allow "packfact" times the minimal
955 * width we have just added up, partly to allow for the stuff at the
956 * start of each score (more CLEFSIGs to be inserted after we know
957 * where the FEEDs are going to be), and partly so things can spread
960 lowscale = packfact * totwidth / totpseudodur;
961 tryabs(start_p, lowscale, &scores, measinscore);
964 * If the whole chunk fits on one score, just set the absolute coords
965 * for this score and get out.
968 setabs(start_p, scores, measinscore);
974 * However many scores tryabs() says were needed, that is what we will
975 * require. But it's likely that the last score is far from filled up.
976 * It would look bad to just spread out the stuff in the last score.
977 * We want to "balance the load".
979 * So make up a new scale (highscale) which would probably force us to
980 * use an additional score. Then loop, binary searching, to find a
981 * value for scale almost as big as possible without forcing a new
985 highscale = 3.0 * lowscale;
986 for (trial = 0; trial < 12; trial++) {
987 midscale = (lowscale + highscale) / 2;
988 tryabs(start_p, midscale, &scores, measinscore);
989 if (scores > reqscores) {
990 highscale = midscale;
991 } else { /* must be equal, can never be less */
996 * If the last one we tried is not a good one, we have to run tryabs
997 * again to reset the scores array properly.
999 if (midscale != lowscale) {
1000 tryabs(start_p, lowscale, &scores, measinscore);
1003 setabs(start_p, scores, measinscore);
1011 * Abstract: Given trial scale, find how many scores are needed, etc.
1015 * Description: This function, given a proposed scale factor for a chunk
1016 * delimited by FEEDs, figures out how many measures would
1017 * fit on each score.
1021 tryabs(start_p, scale, scores_p, measinscore)
1023 struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
1024 double scale; /* inches per "whole" unit of time */
1025 int *scores_p; /* return number of scores needed */
1026 short measinscore[]; /* return number of measures in each score */
1029 struct MAINLL *mainll_p;/* points along main linked list */
1030 struct MAINLL *new_p; /* points at first struct in new measure */
1031 struct MAINLL *ml2_p; /* another general pointer into MAINLL */
1032 struct MAINLL *prevfeed_p;/* where previous FEED is or would go */
1033 float remwidth; /* width remaining on this score */
1034 float userdelta; /* (user right margin) - (normal right margin)*/
1035 int atend; /* are we at the end of the chunk? */
1036 struct CLEFSIG clefsig; /* temporary CLEFSIG for start of each score */
1037 struct BAR bar; /* temp BAR; may be need by the above CLEFSIG*/
1038 float measwidth; /* width needed by one measure */
1039 float adjust; /* bar line adjust if last measure in score */
1040 int ressv; /* do we have to re-initstructs() and re-SSV?*/
1043 debug(32, "tryabs file=%s line=%d scale=%f", start_p->inputfile,
1044 start_p->inputlineno, (float)scale);
1045 /* must apply all SSVs from start, to get the right clef/key/time; */
1046 setssvstate(start_p);
1051 * Set up for beginning of first score in this chunk.
1052 * Find out how much width is available, allowing for
1053 * margins and stuff to the left (labels, etc.).
1055 *scores_p = 0; /* no scores yet */
1056 /* left margin may have user override; for now, assume right doesn't */
1057 remwidth = PGWIDTH - eff_rightmargin((struct MAINLL *)0)
1058 - eff_leftmargin(start_p);
1059 remwidth -= width_left_of_score(start_p);
1063 * If the user overrode the right margin at the end of this chunk, we
1064 * need to know the difference between what they requested and what the
1065 * normal value is. If they didn't, userdelta will be zero.
1067 userdelta = eff_rightmargin(start_p->next) -
1068 eff_rightmargin((struct MAINLL *)0);
1070 prevfeed_p = start_p; /* init previous FEED to the start of chunk */
1073 * We need to set up a provisional CLEFSIG containing what would need
1074 * to be printed at the start of this new score. We can't put it in
1075 * the real MAINLL yet, since this function is just trying a
1076 * possibility, and cannot alter MAINLL for real. Set a pointer to
1077 * a bar, which in real life would be allocated by fillclefsig.
1078 * Subtract the clefsig's width from what we have left to work with.
1080 (void)memset((char *)&clefsig, 0, sizeof(clefsig));
1081 (void)memset((char *)&bar, 0, sizeof(bar));
1082 clefsig.bar_p = &bar;
1083 fillclefsig(&clefsig, mainll_p);
1084 remwidth -= width_clefsig(&clefsig) + CSP(&clefsig);
1086 /* loop through chunk, once per measure, finding where FEEDs would go*/
1088 /* get width of this measure, and where next one starts */
1089 new_p = trymeasure(mainll_p, scale, &measwidth, &adjust,&ressv);
1091 atend = endchunk(new_p); /* last measure of chunk? */
1093 if (!atend && (measwidth - adjust) <= remwidth ||
1094 atend && (measwidth - adjust) <= remwidth - userdelta ||
1095 measinscore[*scores_p] == 0) {
1097 * There is room for this measure on this score, or
1098 * there are no measures here yet so we better force
1099 * this one onto there. We'll fail later if this
1100 * in fact cannot fit.
1101 * Subtract its width from what's left on this score,
1102 * and increment the number of measures on it. Point
1103 * at the next measure.
1105 remwidth -= measwidth;
1106 measinscore[*scores_p]++;
1109 /* if we are at the end, inc no. of scores & return */
1116 * There is not room for this measure on this score.
1117 * Increment the number of scores needed.
1122 * If this last measure ended with SSV(s) after the
1123 * bar line that would cause a CLEFSIG, we need to
1124 * undo the change so that the new score will start
1125 * with the old info. Sadly, we'll have to init
1126 * the SSVs and apply them over from the beginning.
1129 setssvstate(mainll_p);
1133 * Find out how much width is available, allowing for
1134 * margins and stuff to the left (labels, etc.).
1135 * For now, assume this is not the last score, so no
1136 * user margin override.
1138 remwidth = PGWIDTH - eff_rightmargin((struct MAINLL *)0)
1139 - eff_leftmargin((struct MAINLL *)0);
1140 remwidth -= pwidth_left_of_score(mainll_p, prevfeed_p);
1142 prevfeed_p = mainll_p; /* where feed would go */
1145 * We need to set up a provisional CLEFSIG containing
1146 * what would need to be printed at the start of this
1147 * new score. We can't put it in the real MAINLL yet,
1148 * since this function is just trying a possibility,
1149 * and cannot alter MAINLL for real. In case a repeat
1150 * start is going to be needed, have a bar pointer
1151 * ready. Subtract the clefsig's width from what we
1152 * have left to work with.
1154 (void)memset((char *)&clefsig, 0, sizeof(clefsig));
1155 (void)memset((char *)&bar, 0, sizeof(bar));
1156 clefsig.bar_p = &bar;
1157 fillclefsig(&clefsig, mainll_p);
1158 remwidth -= width_clefsig(&clefsig) + CSP(&clefsig);
1159 measinscore[*scores_p] = 0; /* no bars here yet */
1162 * If the measure we just figured is too wide for the
1163 * new score we are about to begin, it must be that
1164 * we are just padding things too much. (If there
1165 * really is too much stuff in the measure, we'll fail
1166 * later.) So assume we'll cram in it anyway, set up
1167 * 0 width remaining, and prepare for next measure.
1168 * We have to reapply the SSVs we removed above, since
1169 * we won't be calling trymeasure() again for that
1172 * If the measure fits, don't do any of this. Just let
1173 * trymeasure figure the same one over again, next
1176 if (!atend && measwidth > remwidth ||
1177 atend && measwidth > remwidth - userdelta) {
1179 for (ml2_p = mainll_p; ml2_p != new_p;
1180 ml2_p = ml2_p->next) {
1181 if (ml2_p->str == S_SSV)
1182 asgnssv(ml2_p->u.ssv_p);
1186 measinscore[*scores_p] = 1;
1189 /* if at the end, fix no. of scores & ret */
1202 * Abstract: Is this MLL item near the end of a chunk?
1204 * Returns: YES or NO
1206 * Description: This function, given a main linked list structure, finds out
1207 * whether there is nothing left in this chunk of the MLL other
1208 * than possibly SSVs/PRHEADs/LINEs/CURVEs. The very end of a
1209 * chunk is determined by the end of the MLL, or the FEED that
1210 * begins the next chunk.
1216 struct MAINLL *mainll_p; /* points into the MAINLL */
1219 /* loop past any SSVs or PRHEADs */
1220 while (mainll_p != 0 && (mainll_p->str == S_SSV ||
1221 mainll_p->str == S_PRHEAD ||
1222 mainll_p->str == S_LINE ||
1223 mainll_p->str == S_CURVE))
1224 mainll_p = mainll_p->next;
1226 /* if we hit the end or a FEED, we found the end of this chunk */
1227 if (mainll_p == 0 || mainll_p->str == S_FEED)
1233 * Name: adjust_measwid4mrpt()
1235 * Abstract: If the measure contains a mrpt, adjust the measure's width.
1237 * Returns: the new (possibly increased) measure width
1239 * Description: This function, given the supposed width of a measure and the
1240 * first chord of the measure, looks to see if there is an mrpt
1241 * in the measure. If so, it enlarges the chord(s) in the measure
1242 * if necessary, to make sure there's enough room for the symbol.
1246 adjust_measwid4mrpt(oldmeaswid, ch_p)
1248 double oldmeaswid; /* old measure width */
1249 struct CHORD *ch_p; /* points at a chord, should be first chord in meas */
1252 int gotmrpt; /* is there an mrpt? */
1253 struct GRPSYL *gs_p; /* point down list of GRPSYLs in chord */
1254 float newmeaswid; /* possible new measure width */
1255 float thismrpt; /* space needed by one mrpt and its padding */
1256 float increase; /* how much bigger must we make the measure? */
1260 * Scan down the first chord and see if any groups have an mrpt.
1264 for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
1265 if (is_mrpt(gs_p)) {
1267 /* get width of this mrpt + its padding, if any */
1268 thismrpt = width(FONT_MUSIC, DFLT_SIZE, C_MEASRPT) *
1269 svpath(gs_p->staffno, STAFFSCALE)->staffscale +
1271 if (thismrpt > newmeaswid) {
1272 newmeaswid = thismrpt;
1278 return (oldmeaswid); /* no mrpt, return original width */
1280 /* if measure is already wider than all mrpts, return unchanged */
1281 if (oldmeaswid >= newmeaswid)
1282 return (oldmeaswid);
1285 * Some staff(s) have mrpts, and the existing chord(s) add up to
1286 * narrower than the width of an mrpt. It's really rare that this
1287 * could happen if there is only one chord. So we will handle it by
1288 * forcing the first chord to be wider, rather than allocating the
1289 * extra amongst all the chords.
1291 if (ABSDIFF(ch_p->width, TEMPMRPTWIDTH) < 0.001) {
1292 /* first chord is all mrpt, so no other chords exist; */
1293 /* the 0.001 is to allow for roundoff error */
1294 ch_p->c[RE] = newmeaswid / 2.0;
1295 ch_p->c[RW] = -newmeaswid / 2.0;
1296 ch_p->width = newmeaswid;
1298 /* add extra to the right side of the first chord */
1299 increase = newmeaswid - oldmeaswid;
1300 ch_p->c[RE] += increase;
1301 ch_p->width += increase;
1304 return (newmeaswid);
1308 * Name: fillclefsig()
1310 * Abstract: Fill the CLEFSIG for after a FEED.
1314 * Description: This function, given an empty CLEFSIG structure and a pointer
1315 * to a FEED structure in the MAINLL, fills the CLEFSIG according
1316 * to what should be printed. If called from tryabs() (bar_p !=
1317 * 0), the bar will be set to REPEATSTART if need be, based on the
1318 * type of the preceding bar. If called from setabs() (bar_p ==
1319 * 0), the same will be done, if need be, after allocating a BAR
1320 * and setting the pointer to it. In one bizarre case, abschunk()
1321 * calls here directly, and this is treated the same as tryabs();
1326 fillclefsig(clefsig_p, feed_p)
1328 struct CLEFSIG *clefsig_p; /* points at empty clefsig to be filled in */
1329 struct MAINLL *feed_p; /* points at a FEED in the MAINLL */
1332 struct MAINLL *mainll_p;/* points along the MAINLL */
1333 struct BAR *realbar_p; /* point at bar before this feed */
1334 float barpad; /* padding on that bar */
1335 int s; /* staff number */
1339 * On every visible staff, the clef and key signature are to
1342 for (s = 1; s <= Score.staffs; s++) {
1343 if (svpath(s, VISIBLE)->visible == NO)
1344 continue; /* invisible */
1345 clefsig_p->prclef[s] = YES;
1346 clefsig_p->sharps[s] = eff_key(s);
1349 /* clefs to be printed should be regular size */
1350 clefsig_p->clefsize = DFLT_SIZE;
1353 * The time signature is to be printed on the first score, or if
1354 * it just changed. Search back to see if there was a CLEFSIG just
1355 * before this FEED where the time changed, or if this is the first
1358 for (mainll_p = feed_p->prev; mainll_p != 0 &&
1359 mainll_p->str != S_BAR && mainll_p->str != S_CLEFSIG;
1360 mainll_p = mainll_p->prev)
1363 /* see chkrestart() for explanation of the bar_p->c[AY] part of this */
1364 if (mainll_p == 0 ||
1365 mainll_p->str == S_CLEFSIG &&
1366 mainll_p->u.clefsig_p->prtimesig == YES ||
1367 mainll_p->str == S_BAR &&
1368 mainll_p->u.bar_p->c[AY] > 0.0)
1369 clefsig_p->prtimesig = YES;
1372 * If the preceding BAR (if any) was a REPEATSTART or REPEATBOTH, it
1373 * has to be "split up". Search back to find this bar.
1375 for (mainll_p = feed_p->prev; mainll_p != 0 && mainll_p->str != S_BAR;
1376 mainll_p = mainll_p->prev)
1379 if (clefsig_p->bar_p != 0) {
1381 * tryabs() called us. If there is a preceding bar, and it is
1382 * REPEATSTART or REPEATBOTH, it would have to be "split", and
1383 * our pseudo bar must be made a REPEATSTART. Otherwise, the
1384 * the pseudo bar should be INVISBAR since nothing really
1385 * should be printed there. Since tryabs() called us, we can't
1386 * tamper with the preceding (real) bar. That's okay; the
1387 * change would just make that bar slightly narrower, so
1388 * things will still fit on that score.
1390 if (mainll_p != 0 &&
1391 (mainll_p->u.bar_p->bartype == REPEATSTART ||
1392 mainll_p->u.bar_p->bartype == REPEATBOTH)) {
1393 clefsig_p->bar_p->bartype = REPEATSTART;
1395 clefsig_p->bar_p->bartype = INVISBAR;
1399 * setabs() called us, so we must allocate a pseudo bar and
1400 * point the clefsig at it. The same splitting rules apply as
1401 * for tryabs(), except since we're now doing it for real, we
1402 * have to really alter the preceding bar's bar type in those
1403 * cases. This preceding bar's AW and AX must also be
1404 * adjusted, since the bar is now going to be narrower than it
1407 CALLOC(BAR, clefsig_p->bar_p, 1);
1409 if (mainll_p != 0 &&
1410 (mainll_p->u.bar_p->bartype == REPEATSTART ||
1411 mainll_p->u.bar_p->bartype == REPEATBOTH)) {
1413 realbar_p = mainll_p->u.bar_p;
1414 realbar_p->bartype = realbar_p->bartype == REPEATSTART ?
1415 realbar_p->precbartype : REPEATEND;
1416 realbar_p->c[AW] = realbar_p->c[AE] -
1417 width_barline(realbar_p);
1418 /* to get AX, temporarily set padding to 0; find the */
1419 /* width of the resulting nonpadded bar, and subtract*/
1420 /* half of that from AE; then restore padding */
1421 barpad = realbar_p->padding;
1422 realbar_p->padding = 0;
1423 realbar_p->c[AX] = realbar_p->c[AE] -
1424 width_barline(realbar_p) / 2;
1425 realbar_p->padding = barpad;
1426 clefsig_p->bar_p->bartype = REPEATSTART;
1428 clefsig_p->bar_p->bartype = INVISBAR;
1434 * Name: trymeasure()
1436 * Abstract: Find trial width of a measure.
1438 * Returns: Pointer to the first MAINLL structure of the next measure,
1439 * or 0 if we hit the end of MAINLL.
1441 * Description: This function, given a pointer to the first MAINLL structure
1442 * in a measure (or the FEED preceding), finds and fills in the
1443 * width of the measure.
1446 static struct MAINLL *
1447 trymeasure(mainll_p, scale, measwidth_p, adjust_p, ressv_p)
1449 struct MAINLL *mainll_p; /* points first thing in meas, or FEED */
1450 double scale; /* inches per "whole" unit of time */
1451 float *measwidth_p; /* width of measure to be filled in */
1452 float *adjust_p; /* bar line adjust, to be filled in; if last
1453 * meas in score, bar shouldn't be padded on
1454 * right, so subtract this for measwidth */
1455 int *ressv_p; /* did we apply a CLEFSIG-causing SSV? */
1458 struct CHORD *ch_p; /* point at a chord */
1459 struct TIMEDSSV *tssv_p;/* point along timed SSV list */
1460 float idealwidth; /* the width a chord should be, based on time*/
1464 pfatal("invalid mainll_p argument (0) to trymeasure");
1466 *ressv_p = NO; /* assume no SSVs for now */
1468 /* every measure has one CHHEAD; find it */
1469 while (mainll_p != 0 && mainll_p->str != S_CHHEAD)
1470 mainll_p = mainll_p->next;
1472 pfatal("missing CHHEAD near end of main linked list");
1477 * For each chord, find out how much width it "deserves",
1478 * based on its pseudodur. But if it requires more space
1479 * than that, give it what it needs. Accumulate in *measwidth_p.
1481 for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
1482 ch_p = ch_p->ch_p) {
1484 idealwidth = scale * ch_p->pseudodur;
1485 /* but a chord of all compressible, nonpadded spaces */
1486 /* deserves no width */
1487 if (ch_p->width == 0)
1489 *measwidth_p += MAX(idealwidth, ch_p->width);
1493 * Find the bar line and add in its width.
1495 while (mainll_p->str != S_BAR)
1496 mainll_p = mainll_p->next;
1497 *measwidth_p += width_barline(mainll_p->u.bar_p);
1499 /* apply any timed SSVs */
1500 for (tssv_p = mainll_p->u.bar_p->timedssv_p; tssv_p != 0;
1501 tssv_p = tssv_p->next) {
1502 asgnssv(&tssv_p->ssv);
1503 *ressv_p = YES; /* remember we've assigned SSVs */
1506 /* need this in case this will be the last measure in the score */
1507 *adjust_p = eos_bar_adjust(mainll_p->u.bar_p);
1509 mainll_p = mainll_p->next; /* point after bar line */
1510 /* if end of MAINLL or next measure is starting up, return now */
1511 if (mainll_p == 0 || (mainll_p->str != S_SSV &&
1512 mainll_p->str != S_CLEFSIG))
1515 /* apply any SSVs at this point */
1516 while (mainll_p != 0 && mainll_p->str == S_SSV) {
1517 asgnssv(mainll_p->u.ssv_p);
1518 mainll_p = mainll_p->next;
1519 *ressv_p = YES; /* remember we've assigned SSVs */
1522 if (mainll_p != 0 && mainll_p->str == S_CLEFSIG) {
1523 *measwidth_p += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p) +
1524 CSP(mainll_p->u.clefsig_p);
1525 mainll_p = mainll_p->next;
1534 * Abstract: Sets horizontal absolute coordinates for one chunk.
1538 * Description: This function, given a chunk of the piece delimited by FEEDs,
1539 * and the number of measures to be put on each score, loops
1540 * through the scores, inserting FEEDs between them, and calling
1541 * setabsscore() to set the horizontal absolute coordinates.
1545 setabs(start_p, scores, measinscore)
1547 struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
1548 int scores; /* number of scores this chunk needs */
1549 short measinscore[]; /* number of measures in each score */
1552 struct MAINLL *mainll_p;/* points along main linked list */
1553 struct MAINLL *ml2_p; /* another general pointer into MAINLL */
1554 int score; /* score number, 0 to scores-1 */
1555 int n; /* loop counter */
1558 debug(16, "setabs file=%s line=%d scores=%d", start_p->inputfile,
1559 start_p->inputlineno, scores);
1560 /* must apply all SSVs from start, to get the right clef/key/time; */
1561 setssvstate(start_p);
1563 /* point at first item in first measure of chunk (skip initial FEED) */
1564 mainll_p = start_p->next;
1566 for (score = 0; score < scores; score++) {
1567 /* the first score already has a FEED; insert if later score */
1569 ml2_p = newMAINLLstruct(S_FEED, 0);
1570 insertMAINLL(ml2_p, mainll_p->prev);
1572 mainll_p = mainll_p->prev; /* point at the FEED */
1575 * Insert CLEFSIG following the FEED, and fill as needed.
1576 * fillclefsig() will also allocate a BAR, and point the
1577 * clefsig at it. If the previous bar line was a REPEATSTART
1578 * or REPEATBOTH, it will set REPEATSTART in the new pseudo
1579 * BAR, and alter the preceding bar as necessary.
1581 ml2_p = newMAINLLstruct(S_CLEFSIG, 0);
1582 insertMAINLL(ml2_p, mainll_p);
1583 fillclefsig(ml2_p->u.clefsig_p, mainll_p);
1584 ml2_p->u.clefsig_p->multinum = getmultinum(ml2_p);
1587 * Find end of score by searching forward the correct number
1588 * of measures. Each measure begins with a CHHEAD, and a block
1589 * begins with a BLOCKHEAD, so stop at either of these. Call
1590 * a subroutine to process this score.
1592 ml2_p = ml2_p->next; /* point at CHHEAD */
1593 for (n = 0; n < measinscore[score]; n++) {
1595 ml2_p = ml2_p->next;
1596 } while (ml2_p != 0 && ml2_p->str != S_CHHEAD &&
1597 ml2_p->str != S_BLOCKHEAD);
1599 chkrestart(mainll_p, ml2_p);
1600 if (hidestaffs(mainll_p, ml2_p) == YES) {
1601 /* if we had to force any staffs invisible, we have to
1602 * reapply SSVs so that the new ones we inserted take
1604 setssvstate(start_p);
1606 setabsscore(mainll_p, ml2_p);
1612 * Name: chkrestart()
1614 * Abstract: Check for restart bars and remove if necessary.
1618 * Description: This function, given one score's worth of input, checks for
1619 * restart bars. These are used for making a gap in the score.
1620 * So when they are the first or last bar in a score, they don't
1621 * make sense, and should be removed. Well, not simply removed;
1622 * various things need to be done to the main linked list.
1626 chkrestart(start_p, end_p)
1628 struct MAINLL *start_p; /* point at the initial FEED of this score */
1629 struct MAINLL *end_p; /* point after the last thing on this score */
1632 struct MAINLL *mainll_p;/* points along main linked list */
1633 struct MAINLL *m2_p; /* another pointer along main linked list */
1634 int s; /* staff number */
1637 /* find first bar on this score; there has to be at least one */
1638 for (mainll_p = start_p; mainll_p->str != S_BAR;
1639 mainll_p = mainll_p->next)
1642 if (mainll_p->u.bar_p->bartype == RESTART) {
1644 * The first bar on the score is a restart. So the score would
1645 * start with whitespace followed by the restart bar, which
1646 * would look bad. So make the restart into an invisbar (which
1647 * eliminates the whitespace). A little negative padding is
1648 * needed to make things line up. Clean out the beginning of
1649 * score clefsig so that nothing prints there. The former
1650 * restart's clefsig will print at the start of the line as if
1651 * it were the beginning of line clefsig.
1653 mainll_p->u.bar_p->bartype = INVISBAR;
1654 mainll_p->u.bar_p->padding = -0.12;
1656 start_p->next->u.clefsig_p->prtimesig = NO;
1657 for (s = 1; s <= MAXSTAFFS; s++) {
1658 start_p->next->u.clefsig_p->prclef[s] = NO;
1659 start_p->next->u.clefsig_p->sharps[s] = 0;
1660 /* no need to zap the naturals, already 0 */
1664 /* find the last bar on this score */
1665 m2_p = 0; /* keep lint happy */
1666 for ( ; mainll_p != end_p; mainll_p = mainll_p->next) {
1667 if (mainll_p->str == S_BAR)
1671 if (m2_p->u.bar_p->bartype == RESTART) {
1673 * The last bar on the score is a restart. So the score would
1674 * end with whitespace followed by a clefsig, which would look
1675 * bad. So make the restart into an invisbar (which eliminates
1676 * the whitespace) and remove the clefsig from the MLL, since
1677 * we don't want to show those things at a restart. The next
1678 * score will now be like a restart.
1680 m2_p->u.bar_p->bartype = INVISBAR;
1681 m2_p->u.bar_p->padding = 0;
1683 mainll_p = m2_p; /* remember bar */
1685 /* find the clefsig; defensive check for end of MLL */
1686 for ( ; m2_p != 0 && m2_p->str != S_CLEFSIG; m2_p = m2_p->next)
1689 pfatal("the last bar in the piece is a restart");
1692 * When it comes time to create the coming feed and clefsig,
1693 * that clefsig's value for prtimesig depends on the one in the
1694 * clefsig we are about to remove. So as a special kluge, if
1695 * that value is YES, set the bar's AY to a positive number.
1696 * It will get overwritten in absvert.c.
1698 if (m2_p->u.clefsig_p->prtimesig == YES) {
1699 mainll_p->u.bar_p->c[AY] = 1.0;
1702 m2_p->prev->next = m2_p->next;
1703 m2_p->next->prev = m2_p->prev;
1704 FREE(m2_p->u.clefsig_p);
1710 * Name: setabsscore()
1712 * Abstract: Sets horizontal absolute coordinates for one score.
1716 * Description: This function, given one score's worth of input, decides how
1717 * to space everything horizontally to look pleasing, and then
1718 * sets the horizontal absolute coordinates.
1722 setabsscore(start_p, end_p)
1724 struct MAINLL *start_p; /* point at the initial FEED of this score */
1725 struct MAINLL *end_p; /* point after the last thing on this score */
1728 struct MAINLL *mainll_p;/* points along main linked list */
1729 struct MAINLL *m2_p; /* another pointer along main linked list */
1730 struct CHORD *ch_p; /* point at a chord */
1731 struct CHORD *firstch_p;/* point at first chord in a measure */
1732 struct BAR *bar_p; /* convenient pointer at a clefsig's bar */
1733 struct MAINLL *mm_p; /* another pointer along MLL */
1734 struct MAINLL *lastbarmll_p; /* remember the last bar in the score */
1735 struct CLEFSIG *clefsig_p; /* point at a clefsig */
1736 struct TIMEDSSV *tssv_p;/* point along a timed SSV list */
1737 float prevbarae; /* remember previous bar's AE */
1738 float wid; /* temp variable, width of something */
1739 float eff_right; /* effective right margin */
1740 float scorewidth; /* total width allowed for the score */
1741 float totwidth; /* total minimum width */
1742 float totwhole; /* total equivalent whole notes of time */
1743 float chw; /* total minimum width of chords */
1744 float notespace; /* space for chords */
1745 float nnotespace; /* space for expandable chords */
1746 float ntotwhole; /* total equiv wholes for expandables */
1747 float inchpwhole; /* inches each whole note should have */
1748 float expanded; /* width of something after expansion */
1749 float absx; /* absolute x coordinate */
1750 float leftx, rightx; /* start and end positions of a measure */
1751 float eff; /* effective width */
1752 int toowide; /* number of chords wider than they deserve */
1753 int ntoowide; /* new no. of chords wider than deserved */
1756 debug(32, "setabsscore file=%s line=%d",
1757 start_p->inputfile, start_p->inputlineno);
1758 firstch_p = 0; /* keep lint happy; will be set before used */
1759 prevbarae = 0.0; /* keep lint happy; will be set before used */
1760 lastbarmll_p = 0; /* keep lint happy; will be set before used */
1763 * Get total available width on this score.
1766 /* find last feed or last bar, whichever comes last */
1767 for (m2_p = Mainlltc_p; m2_p->str != S_FEED &&
1768 m2_p->str != S_BAR; m2_p = m2_p->prev)
1770 if (m2_p->str == S_FEED) {
1771 /* a feed after the last bar; use it */
1772 eff_right = eff_rightmargin(m2_p);
1774 /* no feed after the last bar */
1775 eff_right = eff_rightmargin((struct MAINLL *)0);
1779 * end_p must be the chhead of the following measure. Its prev
1780 * may be a user FEED. (The CLEFSIG which should be between
1781 * them has not been inserted yet.)
1783 if (end_p->prev->str == S_FEED) {
1784 /* it is a feed, so use it */
1785 eff_right = eff_rightmargin(end_p->prev);
1788 eff_right = eff_rightmargin((struct MAINLL *)0);
1792 scorewidth = PGWIDTH - eff_right - eff_leftmargin(start_p);
1793 scorewidth -= width_left_of_score(start_p);
1796 * Accumulate the total minimum width, total pseudodur in equivalent
1797 * wholes, and the total minimum width needed by chords.
1802 for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next){
1803 switch (mainll_p->str) {
1806 /* assign to keep time sig accurate */
1807 asgnssv(mainll_p->u.ssv_p);
1812 * Add in min widths & time of all chords in measure.
1813 * Skip any leading space chords in determining first.
1814 * (Actually, only compressible, nonpadded spaces.)
1815 * The west part of the first chord is considered part
1816 * a fixed width. The "effwidth" of a chord is its
1817 * east part plus the west part of the next chord, if
1820 for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0 &&
1821 ch_p->width == 0; ch_p = ch_p->ch_p)
1825 totwidth -= ch_p->c[RW]; /* first nonspace */
1826 for ( ; ch_p != 0; ch_p = ch_p->ch_p) {
1827 totwidth += effwidth(ch_p);
1828 chw += effwidth(ch_p);
1830 /* count time only if not a chord of */
1831 /* compressible, nonpadded spaces */
1832 if (ch_p->width != 0)
1833 totwhole += ch_p->pseudodur;
1839 * If this clefsig is the last thing on this score
1840 * (except possibly the FEED that starts the next chunk)
1841 * find the preceding bar line. If that bar has
1842 * hidechanges set, it means that we are not to print
1845 if (mainll_p->next == end_p ||
1846 mainll_p->next->str == S_FEED) {
1847 for (m2_p = mainll_p; m2_p->str != S_BAR;
1850 if (m2_p->u.bar_p->hidechanges) {
1851 mainll_p->u.clefsig_p->hide = YES;
1852 mainll_p->u.clefsig_p->effwidth = 0.0;
1856 /* width of clef/key/time/repeatstart when needed */
1857 totwidth += EFF_WIDCLEFSIG(mainll_p->u.clefsig_p);
1858 /* pad clefsig, unless it's the last thing on score */
1859 if (mainll_p->next != end_p &&
1860 mainll_p->next->str != S_FEED)
1861 totwidth += CSP(mainll_p->u.clefsig_p);
1866 totwidth += width_barline(mainll_p->u.bar_p) +
1867 mainll_p->u.bar_p->padding;
1868 /* apply any timed SSVs */
1869 for (tssv_p = mainll_p->u.bar_p->timedssv_p;
1870 tssv_p != 0; tssv_p = tssv_p->next) {
1871 asgnssv(&tssv_p->ssv);
1873 lastbarmll_p = mainll_p;
1879 * If the last bar is truly at the end of the line, it doesn't need its
1880 * full width, because there is no padding after it. But when there is
1881 * a visible clefsig with time or sig there, the bar is not at the end.
1883 for (mm_p = lastbarmll_p; mm_p != 0; mm_p = mm_p->next) {
1884 if (mm_p->str == S_STAFF || mm_p->str == S_CLEFSIG) {
1888 if (mm_p == 0 || mm_p->str != S_CLEFSIG ||
1889 mm_p->u.clefsig_p->hide == YES) {
1890 /* no visible clefsig; get rid of padding */
1891 totwidth -= eos_bar_adjust(lastbarmll_p->u.bar_p);
1893 /* If there is a clefsig, but it has hidechanges,
1894 * or it has no time sigature or any key signatures,
1895 * it needs to be moved to the edge of the score. */
1896 if (mm_p->u.clefsig_p->prtimesig == NO) {
1898 for (s = 1; s <= MAXSTAFFS; s++) {
1899 if ((mm_p->u.clefsig_p->sharps[s] != 0 ||
1900 mm_p->u.clefsig_p->naturals[s] != 0) &&
1901 svpath(s, VISIBLE)->visible == YES) {
1905 if (s > MAXSTAFFS) {
1906 totwidth -= eos_bar_adjust(
1907 lastbarmll_p->u.bar_p);
1912 /* fail if even the minimum size for everything doesn't fit */
1913 if (totwidth > scorewidth) {
1914 if (Score.units == INCHES) {
1915 l_ufatal(start_p->inputfile, start_p->inputlineno,
1916 "too much (%f inches) to put in score",
1917 totwidth * Score.scale_factor);
1919 l_ufatal(start_p->inputfile, start_p->inputlineno,
1920 "too much (%f cm) to put in score",
1921 totwidth * Score.scale_factor *
1927 * Only chords are allowed to expand when there is extra space;
1928 * other items have a fixed width. To find how much space is
1929 * available for chords, take the total screen width minus the
1930 * space needed by the fixed-size things.
1932 notespace = scorewidth - (totwidth - chw);
1935 * Some chords' "effwidths" are already wider than what they deserve
1936 * based on their pseudodur. Let them keep that minimum size. We
1937 * will consider their size as fixed and allocate the remaining
1938 * space among chords that deserve more. Remove the too-wide (and
1939 * just right) chords from the totals. This has to be done
1940 * repeatedly, since after each iteration the number of inches
1941 * deserved by each remaining chord shrinks. Leave the loop when
1942 * it is found that all remaining chords deserve to expand.
1944 ntotwhole = totwhole; /* initially assume all may be expandable */
1945 nnotespace = notespace;
1949 * If there are no notes in this score, totwhole will already
1950 * be 0 on the first loop iteration, and there is nothing that
1951 * can expand. Each measure will be very small, just the width
1952 * of the bar line and its padding, and the rightmost bar line
1953 * won't be at the right edge of the score. This is usually a
1954 * useless situation; but if invisbars are used, and "newscore"
1955 * every measure, it provides a way to print blank music paper.
1957 * inchpwhole won't ever get used, but we set it to something
1958 * arbitrary in case lint cares. Then break out of this loop.
1960 if (totwhole == 0.0) {
1965 * Find how much space each whole note worth of chords
1966 * deserves, allocating proportionally. Consider just the
1967 * ones not known to be too big already.
1969 inchpwhole = nnotespace / ntotwhole;
1971 /* start with all chords' time and space */
1972 ntotwhole = totwhole;
1973 nnotespace = notespace;
1975 toowide = ntoowide; /* remember how many last time */
1978 /* remove from consideration ones that are too big already */
1979 for (mainll_p = start_p; mainll_p != end_p;
1980 mainll_p = mainll_p->next) {
1982 if (mainll_p->str == S_CHHEAD) {
1983 /* loop through all chords doing this */
1984 for (ch_p = mainll_p->u.chhead_p->ch_p;
1985 ch_p != 0; ch_p = ch_p->ch_p) {
1986 if (effwidth(ch_p) >=
1987 ch_p->pseudodur * inchpwhole) {
1988 ntotwhole -= ch_p->pseudodur;
1989 nnotespace -= effwidth(ch_p);
1997 * In the (rare) case where nothing is now expandable (every-
1998 * thing is packed perfectly tightly), we should break out now.
1999 * The "<" is defensive.
2004 } while (ntoowide > toowide);
2007 * Now inchpwhole is the number of inches that should be given to each
2008 * whole note worth of chords that deserve to be wider than their
2009 * minimum. Allocate width proportionally to these chords.
2011 for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next){
2012 if (mainll_p->str == S_CHHEAD) {
2013 for (ch_p = mainll_p->u.chhead_p->ch_p;
2014 ch_p != 0; ch_p = ch_p->ch_p) {
2016 /* normal case (proportional) */
2017 expanded = ch_p->pseudodur * inchpwhole;
2019 /* special case to fix space interaction */
2021 /* but a chord of all compressible, */
2022 /* nonpadded spaces deserves no width */
2023 if (ch_p->width == 0)
2026 /* get min dist needed from our X to next's X */
2027 eff = effwidth(ch_p);
2029 /* the dist we'll really have from X to X */
2030 ch_p->fullwidth = MAX(eff, expanded);
2036 * Now that we know everything's width, set all absolute horizontal
2037 * coordinates for this score. The absx variable keeps track of
2038 * where we are, working from left to right. At all times, keep
2039 * track of the start and end of each measure (leftx and rightx)
2040 * and the first chord in it, so we can reposition measure rests.
2042 /* first reset SSVs to how they were at start of this score */
2043 setssvstate(start_p);
2045 start_p->u.feed_p->c[AW] = eff_leftmargin(start_p);
2046 start_p->u.feed_p->c[AE] = PGWIDTH - eff_right;
2047 absx = eff_leftmargin(start_p) + width_left_of_score(start_p);
2048 start_p->u.feed_p->c[AX] = absx;
2049 leftx = 0.0; /* prevent useless 'used before set' warning */
2051 for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next) {
2052 switch (mainll_p->str) {
2054 /* assign to keep time sig accurate */
2055 asgnssv(mainll_p->u.ssv_p);
2059 clefsig_p = mainll_p->u.clefsig_p;
2061 /* this kind partly already handled by preceding bar */
2062 if (clefsig_p->clefsize == SMALLSIZE &&
2063 clefsig_p->hide == NO) {
2064 /* absx points at AE of barline, so add width*/
2065 /* of clef excluding any clef space */
2066 absx += width_clefsig(clefsig_p) -
2067 clefsig_p->widestclef +
2073 /* "beginning of line" or "restart" clefsig */
2074 clefsig_p->wclefsiga = absx;
2075 if (clefsig_p->hide == NO) {
2076 absx += width_clefsig(clefsig_p) +
2079 bar_p = clefsig_p->bar_p;
2081 /* clefsig has a pseudo bar in it; set coords*/
2082 bar_p->c[AE] = absx;
2083 bar_p->c[AW] = absx - width_barline(bar_p);
2084 bar_p->c[AX] = (bar_p->c[AW] + absx) / 2;
2086 /* remember the AE of this pseudobar */
2093 bar_p = mainll_p->u.bar_p;
2094 absx += bar_p->padding;
2096 /* apply any timed SSVs */
2097 for (tssv_p = bar_p->timedssv_p; tssv_p != 0;
2098 tssv_p = tssv_p->next) {
2099 asgnssv(&tssv_p->ssv);
2103 * If this bar is followed by a clefsig, any clefs in
2104 * it must be printed before this bar. Note that any
2105 * padding will go before the clef (see above). But
2106 * the previous measure "ends" after the clefs.
2108 for (m2_p = mainll_p; m2_p != 0 &&
2109 m2_p->str != S_CLEFSIG &&
2110 m2_p->str != S_CHHEAD;
2113 /* if clefsig that belongs to this bar line . . . */
2114 if (m2_p != 0 && m2_p->str == S_CLEFSIG && m2_p->u.
2115 clefsig_p->clefsize == SMALLSIZE &&
2116 m2_p->u.clefsig_p->hide == NO) {
2117 clefsig_p = m2_p->u.clefsig_p;
2120 * Apply SSVs to get the time & clef changes
2121 * that occur at this bar, if any, since we
2122 * are going to print the new values of them.
2123 * After the width_clefsig, restore the SSVs to
2124 * the proper state at this bar line.
2126 for (m2_p = mainll_p; m2_p->str != S_CLEFSIG;
2127 m2_p = m2_p->next) {
2128 if (m2_p->str == S_SSV) {
2129 asgnssv(m2_p->u.ssv_p);
2132 wid = width_clefsig(clefsig_p);
2133 setssvstate(mainll_p);
2135 /* if wid > effwid, this will overlap the */
2136 /* widest clef by that difference */
2137 clefsig_p->wclefsiga = absx -
2138 (wid - clefsig_p->effwidth) +
2139 bardiff(mainll_p, end_p);
2141 /* point absx after any clefs in clefsig */
2142 absx += clefsig_p->effwidth -
2143 (wid - clefsig_p->widestclef);
2144 rightx = clefsig_p->wclefsiga;
2145 } else { /* no relevant clefsig */
2146 rightx = absx; /* prev measure "ends" here */
2148 bar_p->c[AW] = absx;
2149 absx += width_barline(bar_p);
2150 bar_p->c[AE] = absx;
2151 bar_p->c[AX] = (bar_p->c[AW] + bar_p->c[AE]) / 2.0;
2152 fixfullmeas(firstch_p, (leftx + rightx) / 2.0);
2153 leftx = absx; /* next measure starts here */
2156 * for each staff in the measure just ended, set its AE
2157 * to this bar's AW, and set AX to the midpoint now
2158 * that we know both AW and AE.
2160 for (m2_p = mainll_p; m2_p->str != S_CHHEAD;
2161 m2_p = m2_p->prev) {
2162 if (m2_p->str == S_STAFF) {
2163 m2_p->u.staff_p->c[AE] = bar_p->c[AW];
2164 m2_p->u.staff_p->c[AX] =
2165 (m2_p->u.staff_p->c[AW] +
2166 m2_p->u.staff_p->c[AE]) / 2.0;
2170 /* remember the AE of this bar */
2175 /* as we come to each staff, set AW to prev bar's AE */
2176 mainll_p->u.staff_p->c[AW] = prevbarae;
2180 for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0 &&
2181 ch_p->width == 0; ch_p = ch_p->ch_p)
2182 setabschord(ch_p, absx);
2183 if ((firstch_p = ch_p) == 0)
2185 absx -= firstch_p->c[RW];
2186 for (ch_p = firstch_p; ch_p != 0; ch_p = ch_p->ch_p) {
2187 setabschord(ch_p, absx);
2188 absx += ch_p->fullwidth;
2196 * Name: setabschord()
2198 * Abstract: Sets horizontal absolute coordinates for everything in a chord.
2202 * Description: This function, given a chord, and its absolute offset, sets
2203 * the horizontal absolute coordinates of everything in it.
2207 setabschord(ch_p, nomx)
2209 struct CHORD *ch_p; /* point at the chord */
2210 double nomx; /* nominal X coord; may shift it right a bit */
2213 struct GRPSYL *gs_p; /* point at a group or syllable in chord */
2214 struct GRPSYL *g_p; /* point at a group with notes */
2215 float extra; /* width available beyond what chord needs */
2216 int n; /* loop counter */
2220 * Set the CHORD's horizonal absolute coordinates. If the chord had
2221 * no room to expand (effwidth == fullwidth), there's no question
2222 * where its AX has to be. But otherwise, we want to place it close
2223 * to as far left as it can go, but not jammed up against there.
2225 if ((extra = ch_p->fullwidth - effwidth(ch_p)) > 0) {
2226 nomx += (extra > 1.20 ? 0.20 : extra / 6);
2230 ch_p->c[AW] = nomx + ch_p->c[RW];
2231 ch_p->c[AE] = nomx + ch_p->c[RE];
2234 * Loop through all GRPSYLs in this chord, setting absolute horizontal
2235 * coordinates. To avoid the aggravation of dealing with SSVs again,
2236 * don't bother checking if the staffs in question are visible, just
2237 * do it. It doesn't hurt anything to increment garbage.
2239 for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
2241 * For groups, do the group itself and all the notes in it (if
2242 * any), and do the same for all preceding grace groups.
2244 if (gs_p->grpsyl == GS_GROUP) {
2245 g_p = gs_p; /* init to the normal group */
2247 /* do the group itself, based off the chord */
2248 g_p->c[AX] = ch_p->c[AX] + g_p->c[RX];
2249 g_p->c[AW] = ch_p->c[AX] + g_p->c[RW];
2250 g_p->c[AE] = ch_p->c[AX] + g_p->c[RE];
2252 /* do each note, based off the group */
2253 for (n = 0; n < g_p->nnotes; n++) {
2254 g_p->notelist[n].c[AX] = g_p->c[AX] +
2255 g_p->notelist[n].c[RX];
2256 g_p->notelist[n].c[AW] = g_p->c[AX] +
2257 g_p->notelist[n].c[RW];
2258 g_p->notelist[n].c[AE] = g_p->c[AX] +
2259 g_p->notelist[n].c[RE];
2262 } while (g_p != 0 && g_p->grpvalue == GV_ZERO);
2264 /* this is a syllable; just do the syllable */
2265 gs_p->c[AX] = ch_p->c[AX] + gs_p->c[RX];
2266 gs_p->c[AW] = ch_p->c[AX] + gs_p->c[RW];
2267 gs_p->c[AE] = ch_p->c[AX] + gs_p->c[RE];
2275 * Abstract: Find "effective" width of a chord.
2277 * Returns: the width
2279 * Description: This function returns the "effective width" of a chord. This
2280 * is the (minimum) width of its east part, plus the width of the
2281 * west part of the following chord, if there is one.
2287 struct CHORD *ch_p; /* point at the chord */
2290 struct CHORD *next_p;
2293 /* compressible, nonpadded spaces count for nothing */
2294 if (ch_p->width == 0)
2297 /* find the next chord, if any, that is not all compressible, */
2298 /* nonpadded spaces */
2299 for (next_p = ch_p->ch_p; next_p != 0; next_p = next_p->ch_p) {
2300 if (next_p->width != 0)
2305 * If it's the last one in the measure, return the east side of the
2306 * current chord. Otherwise, return that plus the west side of the
2307 * next nonspace chord.
2310 return (ch_p->c[RE]);
2312 return (ch_p->c[RE] - next_p->c[RW]);
2318 * Abstract: Find size difference of end of score bar vs. what it will be.
2322 * Description: When a REPEATSTART occurs at the end of a score, it gets
2323 * changed to a SINGLEBAR, and a REPEATBOTH becomes a REPEATEND
2324 * (the following pseudobar getting set to REPEATSTART). Other
2325 * bartypes are left alone. This function, given the MLL of a bar,
2326 * just returns zero if the bar is not at the end of a score; but
2327 * otherwise it returns the size of that bartype minus the size of
2328 * what it will be replaced by.
2332 bardiff(mainll_p, end_p)
2334 struct MAINLL *mainll_p; /* MLL for the bar line */
2335 struct MAINLL *end_p; /* MLL after end of the score */
2338 struct MAINLL *mll_p; /* for searching the MLL */
2339 struct BAR bar; /* phony BAR structure */
2340 double temp; /* hold the width of the orginal bar */
2344 * Search forward from the bar. If we hit a CHHEAD before hitting the
2345 * end of the score, then this is not the last barline in the score, so
2348 for (mll_p = mainll_p; mll_p != end_p; mll_p = mll_p->next) {
2349 if (mll_p->str == S_CHHEAD)
2353 /* last bar in the score, so do the arithmetic */
2354 switch (mainll_p->u.bar_p->bartype) {
2356 bar.bartype = REPEATSTART;
2357 temp = width_barline(&bar);
2358 bar.bartype = SINGLEBAR;
2359 return (temp - width_barline(&bar));
2362 bar.bartype = REPEATBOTH;
2363 temp = width_barline(&bar);
2364 bar.bartype = REPEATEND;
2365 return (temp - width_barline(&bar));
2368 return (0.0); /* all other types remain the same; difference = 0 */
2372 * Name: fixfullmeas()
2374 * Abstract: Adjust the AE of full measure symbols (mr, multirest, mrpt).
2378 * Description: This function, given the first chord in a measure (the only
2379 * one that can contain a one of these symbols), adjusts the AE
2380 * coord of each GRPSYL in the chords that is one of these. AW
2381 * stays where it is, near the left bar line, except that for
2382 * multirests it moves it to the right, especially for ones
2383 * that are drawn with rest symbols. For multirests and
2384 * measure repeats, AX gets moved leftwards a little, to be
2385 * where it would have been for a measure rest, but for measure
2386 * rests, it stays where it is, not far to the right of that.
2387 * For all three things, AE is put near the right bar line, the
2388 * same distance from it that AW is from the left.
2392 fixfullmeas(ch_p, x)
2394 struct CHORD *ch_p; /* point at the chord */
2395 double x; /* absolute X coord of center of measure */
2398 struct GRPSYL *gs_p; /* point at a group or syllable in chord */
2401 /* in case we have all spaces */
2405 debug(32, "fixfullmeas file=%s line=%d x=%f", ch_p->gs_p->inputfile,
2406 ch_p->gs_p->inputlineno, (float)x);
2408 /* loop through all GRPSYLs, resetting AE/AW for full measure symbols */
2409 for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
2410 /* skip syllables */
2411 if (gs_p->grpsyl != GS_GROUP) {
2415 if (gs_p->is_meas == YES) {
2416 gs_p->c[AE] = x + (x - gs_p->c[AW]);
2417 } else if (gs_p->basictime < -1) {
2418 /* multirest; move the left end to the right a little */
2419 set_staffscale(gs_p->staffno);
2420 gs_p->c[AW] += 2.0 * Stepsize;
2422 * For multirests that are drawn with rest symbols,
2423 * the width may need to be reduced. If half the
2424 * multirest's width exceeds 10 stepsizes, reduce it
2425 * by 0.8 of the excess.
2427 if (gs_p->basictime >= -8 && svpath(gs_p->staffno,
2428 RESTSYMMULT)->restsymmult) {
2429 if (x - gs_p->c[AW] > 10.0 * Stepsize) {
2430 gs_p->c[AW] += ((x - gs_p->c[AW]) -
2431 (10.0 * Stepsize)) * 0.8;
2434 gs_p->c[AE] = x + (x - gs_p->c[AW]);
2438 /* for multirest/mrpt, put AX where it would have been for a mr */
2439 if (ch_p->gs_p->basictime < -1 || is_mrpt(gs_p)) {
2440 ch_p->c[AX] = ch_p->c[AW] +
2441 width(FONT_MUSIC, DFLT_SIZE, C_1REST) / 2;
2446 * Name: restore_grpsyl_west()
2448 * Abstract: Restore all GRPSYLs' west coords when there was a clef there.
2452 * Description: In fixclef() in restsyl.c, we altered the west of any GRPSYL
2453 * that was associated with a midmeasure clef. This was needed so
2454 * that room would be made for the clefs. Now that the packing
2455 * part of abshorz.c is done, we can restore these coords, for the
2456 * benefit of the print phrase.
2460 restore_grpsyl_west()
2463 struct MAINLL *mainll_p; /* point along main linked list */
2464 struct GRPSYL *gs_p; /* point along a GRPSYL list */
2465 struct GRPSYL *gs2_p; /* look for a grace group's main grp */
2466 int vidx; /* voice index */
2467 float size; /* to be used for clef */
2468 float staffscale; /* scale for a staff */
2469 float clefwid; /* width of a clef */
2472 size = 3.0/4.0 * DFLT_SIZE; /* small size clefs */
2475 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2476 switch (mainll_p->str) {
2478 /* keep staffscale up to date */
2479 asgnssv(mainll_p->u.ssv_p);
2482 /* break out to handle staff */
2488 for (vidx = 0; vidx < MAXVOICES; vidx++) {
2489 for (gs_p = mainll_p->u.staff_p->groups_p[vidx];
2490 gs_p != 0; gs_p = gs_p->next) {
2491 if (gs_p->clef == NOCLEF) {
2492 continue; /* no clef, nothing to do */
2495 staffscale = svpath(gs_p->staffno,
2496 STAFFSCALE)->staffscale;
2497 clefwid = (clefwidth(gs_p->clef, YES) +
2498 CLEFPAD) * staffscale;
2499 gs_p->c[RW] += clefwid;
2500 gs_p->c[AW] += clefwid;
2503 * If we are a grace group, look ahead to the
2504 * main group and restore it too.
2506 if (gs_p->grpvalue == GV_ZERO) {
2507 for (gs2_p = gs_p; gs2_p->grpvalue ==
2508 GV_ZERO; gs2_p = gs2_p->next) {
2511 gs2_p->c[RW] += clefwid;
2512 gs2_p->c[AW] += clefwid;
2522 * Abstract: Set INCHPERWHOLE "coordinate" for all structures having it.
2526 * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
2527 * for all nongrace GRPSYLs, notes, chords, and BARs. BARs is
2528 * done right here; for the others, it calls subroutines.
2535 struct MAINLL *mainll_p; /* point along main linked list */
2536 struct MAINLL *m2_p; /* look forward for bar line */
2537 struct GRPSYL *gs_p; /* point along a GRPSYL list */
2538 int timeden; /* denominator of a time signature */
2539 int v; /* index into voices or verses */
2542 debug(16, "setipw");
2543 initstructs(); /* clean out old SSV info */
2546 * Loop through MLL, applying SSVs and processing each visible linked
2549 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2551 switch (mainll_p->str) {
2553 /* this is needed to keep time sig up to date */
2554 asgnssv(mainll_p->u.ssv_p);
2558 /* set the thing for all chords in this measure */
2559 setipwchord(mainll_p);
2563 /* skip this staff if it's invisible */
2564 if (mainll_p->u.staff_p->visible == NO)
2567 /* do all the voices on this staff */
2568 for (v = 0; v < MAXVOICES && (gs_p = mainll_p->u.
2569 staff_p->groups_p[v]) != 0; v++) {
2570 setipwgrpsyl(mainll_p, gs_p);
2573 /* do all the verses on this staff */
2574 for (v = 0; v < mainll_p->u.staff_p->nsyllists; v++) {
2575 gs_p = mainll_p->u.staff_p->syls_p[v];
2576 setipwgrpsyl(mainll_p, gs_p);
2583 * If this is the ending bar line of a score, ignore
2584 * it. The following measure would refer to its
2585 * preceding CLEFSIG's pseudo bar instead. So see if
2586 * we hit a FEED while trying to find the next CHHEAD.
2587 * While doing this, keep track of the denominator of
2588 * the time signature, in case it changes at this bar.
2590 timeden = Score.timeden;
2591 for (m2_p = mainll_p; m2_p != 0 && m2_p->str != S_FEED
2592 && m2_p->str != S_CHHEAD;
2593 m2_p = m2_p->next) {
2594 if (m2_p->str == S_SSV && m2_p->u.ssv_p->used[
2596 timeden = m2_p->u.ssv_p->timeden;
2599 if (m2_p == 0 || m2_p->str == S_FEED)
2603 * This is not the last bar of a score, and m2_p points
2604 * at the CHHEAD of the following measure, with timeden
2605 * being the denominator of the time sig. The space
2606 * between the bar ("count 0") and the first chord
2607 * ("count 1") must be multiplied by the number of
2608 * counts in a whole note (timeden).
2610 mainll_p->u.bar_p->c[INCHPERWHOLE] = timeden *
2611 (m2_p->u.chhead_p->ch_p->c[AX] -
2612 mainll_p->u.bar_p->c[AX]);
2617 * If this clefsig is not at the start of a score,
2618 * ignore it. If it is, it will contain a pseudo bar
2619 * line, and we need to set that bar's coord just like
2620 * for a normal bar line.
2622 if (mainll_p->u.clefsig_p->bar_p == 0)
2625 if (mainll_p->next->str != S_CHHEAD)
2626 pfatal("CLEFSIG with pseudo bar not followed by CHHEAD");
2628 mainll_p->u.clefsig_p->bar_p->c[INCHPERWHOLE] =
2630 (mainll_p->next->u.chhead_p->ch_p->c[AX] -
2631 mainll_p->u.clefsig_p->bar_p->c[AX]);
2638 * Name: setipwgrpsyl()
2640 * Abstract: Set INCHPERWHOLE "coordinate" for the GRPSYLs in one list.
2644 * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
2645 * for all the nongrace GRPSYLs and notes in one voice or verse
2646 * list hanging off a STAFF.
2650 setipwgrpsyl(mainll_p, gs_p)
2652 struct MAINLL *mainll_p; /* point along main linked list */
2653 struct GRPSYL *gs_p; /* point along this GRPSYL list */
2656 struct MAINLL *m2_p; /* look forward for bar line */
2657 struct GRPSYL *ngs_p; /* the next nongrace GRPSYL in list */
2658 float inchperwhole; /* inches per whole note */
2659 int n; /* loop variable */
2662 debug(32, "setipwgrpsyl file=%s line=%d", gs_p->inputfile,
2664 /* get first nongrace GRPSYL */
2665 for ( ; gs_p != 0 && gs_p->grpsyl == GS_GROUP &&
2666 gs_p->grpvalue == GV_ZERO; gs_p = gs_p->next)
2669 pfatal("nothing but grace notes in measure");
2672 * Loop down the list of GRPSYLs. gs_p always points the current
2673 * (nongrace) GRPSYL, whose inches per whole we want to set. ngs_p
2674 * points at the next nongrace GRPSYL.
2677 /* find next nongrace GRPSYL; break if none */
2678 for (ngs_p = gs_p->next;
2679 ngs_p != 0 && ngs_p->grpsyl == GS_GROUP &&
2680 ngs_p->grpvalue == GV_ZERO;
2681 ngs_p = ngs_p->next)
2687 * Distance between them divided by time gives the space a
2688 * a whole note theoretically would have been given.
2690 inchperwhole = (ngs_p->c[AX] - gs_p->c[AX]) /
2691 RAT2FLOAT(gs_p->fulltime);
2693 /* store in GRPSYL & each note (if notes) */
2694 gs_p->c[INCHPERWHOLE] = inchperwhole;
2695 if (gs_p->grpsyl == GS_GROUP && gs_p->grpcont == GC_NOTES) {
2696 for (n = 0; n < gs_p->nnotes; n++)
2697 gs_p->notelist[n].c[INCHPERWHOLE]
2701 /* point current at next, for next iteration */
2706 * We've hit the end of the measure. Loop forward through the MLL
2707 * until we find the bar line.
2709 for (m2_p = mainll_p;
2710 m2_p != 0 && m2_p->str != S_BAR;
2714 pfatal("no bar at end of last measure");
2716 /* this time use bar line as terminating point */
2717 inchperwhole = (m2_p->u.bar_p->c[AX] - gs_p->c[AX]) /
2718 RAT2FLOAT(gs_p->fulltime);
2720 gs_p->c[INCHPERWHOLE] = inchperwhole;
2721 if (gs_p->grpsyl == GS_GROUP && gs_p->grpcont == GC_NOTES) {
2722 for (n = 0; n < gs_p->nnotes; n++)
2723 gs_p->notelist[n].c[INCHPERWHOLE] = inchperwhole;
2728 * Name: setipwchord()
2730 * Abstract: Set INCHPERWHOLE "coordinate" for the CHORDs in one list.
2734 * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
2735 * for all the CHORDs in the list hanging off of one CHHEAD.
2739 setipwchord(mainll_p)
2741 struct MAINLL *mainll_p; /* point at the CHHEAD */
2744 struct MAINLL *m2_p; /* look forward for bar line */
2745 struct CHORD *ch_p, *nch_p; /* point at chords */
2748 debug(32, "setipwchord file=%s line=%d", mainll_p->inputfile,
2749 mainll_p->inputlineno);
2751 * Loop down the list of CHORDs. ch_p always points the current
2752 * CHORD, whose inches per whole we want to set. nch_p points at
2753 * the next CHORD. When nch_p is 0, ch_p is the last chord, and we
2754 * get out of the loop.
2756 for (ch_p = mainll_p->u.chhead_p->ch_p, nch_p = ch_p->ch_p;
2757 nch_p != 0; ch_p = nch_p, nch_p = nch_p->ch_p) {
2759 * Distance between them divided by time gives the space a
2760 * a whole note theoretically would have been given.
2762 ch_p->c[INCHPERWHOLE] = (nch_p->c[AX] - ch_p->c[AX]) /
2763 RAT2FLOAT(ch_p->duration);
2767 * We've hit the end of the measure. Loop forward through the MLL
2768 * until we find the bar line.
2770 for (m2_p = mainll_p;
2771 m2_p != 0 && m2_p->str != S_BAR;
2775 pfatal("no bar at end of last measure");
2777 /* this time use bar line as terminating point */
2778 ch_p->c[INCHPERWHOLE] = (m2_p->u.bar_p->c[AX] - ch_p->c[AX]) /
2779 RAT2FLOAT(ch_p->duration);
2783 * Name: fixendings()
2785 * Abstract: Fix endings at end of score and in pseudobars.
2789 * Description: This function finds endings that start at the final bar of a
2790 * score. It moves them so that they will start at the pseudobar
2791 * at the start of the next score. Then, wherever an ending is
2792 * continuing through a scorefeed, set the pseudobar's endingloc.
2799 struct MAINLL *mainll_p; /* point along main linked list */
2800 struct MAINLL *m2_p; /* look forward for bar line */
2801 struct BAR *bar_p; /* point at preceding bar */
2802 char *str_p; /* point at an ending string */
2805 debug(16, "fixendings");
2807 * Loop through the main linked list, looking for endings that start at
2808 * the end of a score, and moving them. We do it in reverse, to make
2809 * it slightly easier to deal with the case of scores that have only
2810 * one measure on them. (Previous endings won't have been moved yet.)
2812 for (mainll_p = Mainlltc_p; mainll_p != 0; mainll_p = mainll_p->prev) {
2813 if (mainll_p->str != S_BAR)
2815 if (mainll_p->u.bar_p->endingloc != STARTITEM)
2819 * We are at a bar where an ending starts. Find out if this is
2820 * at the end of a score, by seeing if we find a FEED before
2823 for (m2_p = mainll_p->next; m2_p != 0 && m2_p->str != S_BAR &&
2824 m2_p->str != S_FEED; m2_p = m2_p->next)
2827 pfatal("unterminated ending");
2828 if (m2_p->str == S_BAR)
2832 * The ending starts at the last bar of a score. We need to
2833 * know whether a previous ending also ends there, or not. So
2834 * search back to the previous bar. Since we're doing the main
2835 * loop in reverse, we don't have to look at pseudobars, only
2838 for (m2_p = mainll_p->prev; m2_p != 0 && m2_p->str != S_BAR;
2843 * If the previous bar was the end of an ending or not involved
2844 * in one at all, the bar at the end of the score should not be
2845 * involved. Otherwise, there was a preceding ending which
2846 * ends here (where the new one starts), so mark that it ends.
2848 if (m2_p == 0 || m2_p->u.bar_p->endingloc == ENDITEM ||
2849 m2_p->u.bar_p->endingloc == NOITEM)
2851 mainll_p->u.bar_p->endingloc = NOITEM;
2853 mainll_p->u.bar_p->endingloc = ENDITEM;
2855 str_p = mainll_p->u.bar_p->endinglabel;
2856 mainll_p->u.bar_p->endinglabel = 0;
2859 * Find the first feed after this bar that is not at the start
2860 * of a "block", and mark in the following pseudobar that an
2861 * ending starts there.
2863 for (m2_p = mainll_p->next; m2_p != 0 && (m2_p->str != S_FEED ||
2864 m2_p->next != 0 && m2_p->next->str == S_BLOCKHEAD);
2868 pfatal("can't find any music after ending begins");
2870 m2_p->next->u.clefsig_p->bar_p->endingloc = STARTITEM;
2871 m2_p->next->u.clefsig_p->bar_p->endinglabel = str_p;
2875 * Loop again through the main linked list, this time forwards.
2876 * Remember each bar as we find one. Then, adjust the following
2877 * pseudobar if need be.
2879 bar_p = 0; /* no previous bar yet */
2880 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2881 if (mainll_p->str == S_BAR)
2882 bar_p = mainll_p->u.bar_p;
2883 if (mainll_p->str == S_CLEFSIG &&
2884 mainll_p->u.clefsig_p->bar_p != 0) {
2886 * We're at a pseudobar. If the preceding bar was
2887 * inside an ending, mark the pseudobar that way too.
2888 * (If this is the first pseudobar, there won't have
2889 * been any preceding bar.)
2891 if (bar_p != 0 && bar_p->endingloc == INITEM)
2892 mainll_p->u.clefsig_p->bar_p->endingloc
2901 * Abstract: Move rehearsal marks at end of a score to the next score.
2905 * Description: This function finds rehearsal marks at the final bar of a
2906 * score. It moves them so that they will be at the pseudobar
2907 * at the start of the next score.
2914 struct MAINLL *mainll_p; /* point along main linked list */
2915 struct MAINLL *m2_p; /* look forward for bar line */
2918 debug(16, "fixreh");
2920 * Loop through the main linked list, looking for rehearsal marks at
2921 * the end of a score, and moving them.
2923 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2924 if (mainll_p->str != S_BAR)
2926 if (mainll_p->u.bar_p->reh_type == REH_NONE)
2930 * We are at a bar with a rehearsal mark. Find out if this is
2931 * at the end of a score, by seeing if we find a FEED before
2934 for (m2_p = mainll_p->next; m2_p != 0 && m2_p->str != S_BAR &&
2935 m2_p->str != S_FEED; m2_p = m2_p->next)
2938 return; /* nothing more we can do in this case */
2939 if (m2_p->str == S_BAR)
2943 * The ending starts at the last bar of a score. m2_p is at
2944 * the FEED there, but what follows could be either music or a
2945 * "block". If it is a block, we need to keep moving forward
2946 * until we find a FEED followed by music.
2948 while (m2_p != 0 && ! IS_CLEFSIG_FEED(m2_p)) {
2952 return; /* there is no more music, can't move reh */
2956 * We found the FEED. Move the rehearsal mark to the pseudo
2957 * bar after the FEED.
2959 m2_p->next->u.clefsig_p->bar_p->reh_type =
2960 mainll_p->u.bar_p->reh_type;
2961 mainll_p->u.bar_p->reh_type = REH_NONE;
2963 m2_p->next->u.clefsig_p->bar_p->reh_string =
2964 mainll_p->u.bar_p->reh_string;
2965 mainll_p->u.bar_p->reh_string = 0;
2967 m2_p->next->u.clefsig_p->bar_p->dist =
2968 mainll_p->u.bar_p->dist;
2969 mainll_p->u.bar_p->dist = 0;
2971 m2_p->next->u.clefsig_p->bar_p->dist_usage =
2972 mainll_p->u.bar_p->dist_usage;
2973 mainll_p->u.bar_p->dist_usage = SD_NONE;
2978 * Name: clrinhprint()
2980 * Abstract: Clear the inhibitprint on tablature staffs when appropriate.
2984 * Description: This function clears the inhibitprint bit in the first group
2985 * of a tablature staff after a scorefeed. (Because in that
2986 * situation, the group should be printed regardless of the usual
2987 * conditions that inhibit printing.) Also, parentheses should be
2988 * put around every note (fret number) in such groups.
2995 struct MAINLL *mainll_p; /* point along main linked list */
2996 struct GRPSYL *gs_p; /* point at first group */
2997 int sawscorefeed; /* did we just see a scorefeed? */
2998 int vidx; /* voice index */
2999 int n; /* loop through the notes */
3002 debug(16, "clrinhprint");
3003 sawscorefeed = YES; /* "new score" at start of song */
3006 * Loop through main linked list, looking for visible tablature STAFFs,
3007 * scorefeeds, and bar lines.
3009 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
3011 switch (mainll_p->str) {
3013 sawscorefeed = YES; /* just saw a feed */
3016 sawscorefeed = NO; /* next bar, forget the feed */
3020 * If we just saw a scorefeed, and this is a visible
3021 * tablature staff, break to handle it. Otherwise
3022 * continue to the next loop iteration.
3024 if (sawscorefeed == YES &&
3025 mainll_p->u.staff_p->visible == YES &&
3026 is_tab_staff(mainll_p->u.staff_p->staffno))
3033 /* loop through each possible voice on tab staff */
3034 for (vidx = 0; vidx < MAXVOICES; vidx++) {
3036 /* if voice doesn't exist, break out */
3037 gs_p = mainll_p->u.staff_p->groups_p[vidx];
3041 /* if not a note group, there's nothing to do */
3042 if (gs_p->grpcont != GC_NOTES)
3046 * If inhibitprint was set, we need to put parens
3047 * around the notes (frets) and clear the bit.
3049 if (gs_p->inhibitprint == YES) {
3050 for (n = 0; n < gs_p->nnotes; n++)
3051 gs_p->notelist[n].FRET_HAS_PAREN = YES;
3052 gs_p->inhibitprint = NO;
3059 * Name: hidestaffs()
3061 * Abstract: Make staffs invisible if visible=whereused and they're empty.
3065 * Description: If the user set visible=whereused for staffs, up until now we
3066 * have been treating it as visible=y, because the internal field
3067 * visible==YES. But now that we know where all the scorefeeds
3068 * are, this function looks at hidesilent for the given score, and
3069 * when a staff should be invisible based on that, inserts SSVs
3070 * and sets the visible field in the STAFF structures to make it
3075 hidestaffs(mainll_p, ml2_p)
3077 struct MAINLL *mainll_p; /* point at feed at start of score */
3078 struct MAINLL *ml2_p; /* point at last thing on the score */
3081 struct SSV *ssv_p; /* a static SSV containing visibility */
3082 int s; /* staff number */
3083 int firstvis; /* first visible staff in a score */
3084 int foundvis; /* is a staff after first still visible? */
3085 int forced_invis; /* did we force any staffs invisible? */
3086 int ressv; /* must we reapply SSVs from the start? */
3089 debug(16, "hidestaffs");
3092 * Loop through main linked list, applying SSVs and looking for FEEDs.
3093 * When a FEED is found, check all the staffs and make the appropriate
3096 /* find the first (currently) visible staff in this score */
3098 for (s = 1; s <= Score.staffs; s++) {
3099 if (svpath(s, VISIBLE)->visible == YES) {
3104 if (firstvis == 0) {
3105 pfatal("no visible staffs in score");
3109 * Working bottom up, check each currently visible staff to see whether
3110 * it should be made invisible. If so, make it so. But if nothing
3111 * below the first visible staff ends up visible, we leave it alone,
3112 * since at least one staff must always be visible.
3113 * There are cases when silent() has to apply some SSVs. In such
3114 * cases, it sets ressv=YES. Sadly, we have to reapply SSVs from the
3115 * start in that case.
3119 for (s = Score.staffs; s >= firstvis; s--) {
3120 if (s == firstvis && foundvis == NO) {
3121 /* only the top visible staff remains visible */
3124 ssv_p = svpath(s, VISIBLE);
3125 if (ssv_p->visible == NO) { /* already invisible */
3128 if (ssv_p->hidesilent == YES) {
3129 if (silent(mainll_p, ml2_p, s, &ressv) == YES) {
3130 /* silent() forced it invisible */
3133 /* silent() left it visible */
3137 setssvstate(mainll_p);
3139 } else { /* hidesilent == NO */
3140 foundvis = YES; /* leave it visible */
3144 return (forced_invis);
3150 * Abstract: Make a staff invisible for this score, if appropriate.
3152 * Returns: YES if we made it invisible, else NO
3154 * Description: This function decides whether the given staff should be made
3155 * invisible on the given score (line). It should be called only
3156 * when visible==YES and hidesilent==YES. If it should be made
3157 * invisible, it does that by inserting new "input" SSVs into the
3158 * MLL before and after that line, and setting the visible field
3159 * in the staffs to NO. There are cases where this function calls
3160 * asgnssv(); in those cases it sets *ressv_p to YES, otherwise NO.
3164 silent(feedmll_p, ml2_p, s, ressv_p)
3166 struct MAINLL *feedmll_p; /* point along main linked list */
3167 struct MAINLL *ml2_p; /* point at MLL item at end of this score */
3168 int s; /* staff number */
3169 int *ressv_p; /* must the caller reapply SSVs? */
3172 struct MAINLL *mll_p; /* point along MLL */
3173 struct MAINLL *lastbar_p; /* last bar line in score */
3174 struct MAINLL *ins_p; /* point at MLL after which a new SSV goes */
3175 struct MAINLL *new_p; /* point at MLL struct for a new SSV */
3176 struct SSV *ssv_p; /* an SSV */
3177 struct STAFF *staff_p; /* point at a STAFF */
3178 struct STAFF *pstaff_p; /* point at the previous STAFF */
3179 struct GRPSYL *gs_p; /* point at a group or syllable */
3180 struct STUFF *stuff_p; /* point along a STUFF list */
3181 int vidx; /* voice or verse index */
3184 *ressv_p = NO; /* no SSVs have been applied yet */
3186 /* find the last bar line in this score; it's where we should stop */
3188 for (mll_p = feedmll_p->next; mll_p != ml2_p && mll_p->str != S_FEED;
3189 mll_p = mll_p->next) {
3190 if (mll_p->str == S_BAR) {
3194 /* if none, there is no music here */
3195 if (lastbar_p == 0) {
3196 return (NO); /* nothing to hide */
3200 * Loop through this score, checking SSVs and looking in the STAFFs for
3201 * this staff number, looking for reasons we must keep the staff
3204 for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
3205 switch (mll_p->str) {
3208 * To minimize the chances that we will apply an SSV
3209 * and thus have to initstructs() and reapply from the
3210 * beginning, apply only if it is relevent to what we
3213 ssv_p = mll_p->u.ssv_p;
3214 if (ssv_p->context != C_SCORE && ssv_p->staffno != s) {
3215 /* this SSV is irrelevant to our staff */
3218 if (ssv_p->used[VISIBLE] != NO) {
3220 * This SSV could affect our staff's visibility.
3221 * Apply it, and remember that we've now messed
3222 * with the fixed SSVs, and so we'll have to
3223 * reapply from the start.
3229 * This staff started this score with visible==YES and
3230 * hidesilent==YES. We know we are not going to see an
3231 * SSV that causes our staff to go invisible, since
3232 * that would have forced a scorefeed. But we could
3233 * see one that causes our hidesilent value to be NO,
3234 * and in that case we can immediately return NO, since
3235 * it must remain visible.
3237 if (svpath(s, VISIBLE)->hidesilent == NO) {
3243 staff_p = mll_p->u.staff_p;
3244 if (staff_p->staffno != s) {
3245 continue; /* some other staff, ignore */
3247 break; /* break out to handle our staff */
3253 /* decide whether this staff can be made invisible */
3256 * Look at each group in each possible voice. If any contain
3257 * notes, our staff must remain visible.
3259 for (vidx = 0; vidx < MAXVOICES; vidx++) {
3260 for (gs_p = staff_p->groups_p[vidx]; gs_p != 0;
3261 gs_p = gs_p->next) {
3262 if (gs_p->grpcont == GC_NOTES) {
3268 /* if there are any syllables, our staff must remain visible */
3269 if (staff_p->nsyllists != 0) {
3273 /* if there is any stuff, our staff must remain visible */
3274 if (staff_p->stuff_p != 0) {
3279 * If the previous MLL structure is a staff, it could have
3280 * lyrics or "stuff" between it and our staff. If this
3281 * previous staff is already invisible, ignore it since these
3282 * things would be invisible. But the previous staff is
3283 * visible, check for any of them being "between", in which
3284 * case our staff must remain visible.
3286 if (mll_p->prev->str == S_STAFF) {
3287 pstaff_p = mll_p->prev->u.staff_p;
3288 if (pstaff_p->visible == YES) {
3289 for (vidx = 0; vidx < pstaff_p->nsyllists;
3291 if (pstaff_p->sylplace[vidx] ==
3296 for (stuff_p = pstaff_p->stuff_p; stuff_p != 0;
3297 stuff_p = stuff_p->next) {
3298 if (stuff_p->place == PL_BETWEEN) {
3307 * At this point we've looked through everything and found that there
3308 * is no need to keep this staff visible. So we are going to force it
3309 * invisible. If a staff's SSV says visible==NO but it has voice(s)
3310 * with visible==YES, it ends up being visible anyhow. So in addition
3311 * to forcing the staff to visible=NO, we will unset all its voices'
3312 * visibility. Rather than checking how many voices there are, it's
3313 * easiest just to force all possible ones invisible.
3317 * Set ins_p to the SSV after which the new ones should be put. There
3318 * may be a CLEFSIG before the FEED; if so, they should be put before
3319 * there, otherwise just before the FEED. This is to maintain the
3320 * correct ordering of structures; see comment at the end of structs.h.
3321 * If the FEED is at the start, ins_p will be 0.
3323 ins_p = feedmll_p->prev;
3324 if (ins_p != 0 && ins_p->str == S_CLEFSIG) {
3325 ins_p = ins_p->prev;
3328 /* force staff's visible to NO */
3329 new_p = newMAINLLstruct(S_SSV, -1);
3330 ssv_p = new_p->u.ssv_p;
3331 ssv_p->context = C_STAFF;
3333 ssv_p->used[VISIBLE] = YES;
3334 ssv_p->visible = NO;
3335 insertMAINLL(new_p, ins_p);
3337 /* force voices' visible to unset */
3338 for (vidx = 0; vidx < MAXVOICES; vidx++) {
3339 new_p = newMAINLLstruct(S_SSV, -1);
3340 ssv_p = new_p->u.ssv_p;
3341 ssv_p->context = C_VOICE;
3343 ssv_p->voiceno = vidx + 1;
3344 ssv_p->used[VISIBLE] = UNSET;
3345 insertMAINLL(new_p, ins_p);
3348 /* do not let any SSVs on this line alter this staff's visibility */
3349 for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
3350 if (mll_p->str != S_SSV) {
3353 ssv_p = mll_p->u.ssv_p;
3355 * Since we know we are overriding the score, we don't care if
3356 * the score is changing. Just force all staff and voice SSVs
3357 * for this staff to not be setting VISIBLE.
3359 if (ssv_p->context != C_SCORE && ssv_p->staffno == s) {
3360 ssv_p->used[VISIBLE] = NO;
3364 /* the SSVs to be put at the end go after the last bar line */
3368 * Insert "input" SSVs that will cause the staff's fixed SSV and its
3369 * voices' fixed SSVs to be restored to how they would have been if we
3370 * hadn't changed anything. That is the state they are in right now.
3372 new_p = newMAINLLstruct(S_SSV, -1);
3373 ssv_p = new_p->u.ssv_p;
3374 ssv_p->context = C_STAFF;
3376 if (Staff[s-1].used[VISIBLE] == YES) {
3377 ssv_p->used[VISIBLE] = YES;
3378 ssv_p->visible = Staff[s-1].visible;
3379 ssv_p->hidesilent = Staff[s-1].hidesilent;
3381 ssv_p->used[VISIBLE] = UNSET;
3383 insertMAINLL(new_p, ins_p);
3385 for (vidx = 0; vidx < MAXVOICES; vidx++) {
3386 new_p = newMAINLLstruct(S_SSV, -1);
3387 ssv_p = new_p->u.ssv_p;
3388 ssv_p->context = C_VOICE;
3390 ssv_p->voiceno = vidx + 1;
3391 if (Voice[s-1][vidx].used[VISIBLE] == YES) {
3392 ssv_p->used[VISIBLE] = YES;
3393 ssv_p->visible = Voice[s-1][vidx].visible;
3394 ssv_p->hidesilent = Voice[s-1][vidx].hidesilent;
3396 ssv_p->used[VISIBLE] = UNSET;
3398 insertMAINLL(new_p, ins_p);
3401 /* set visible to NO in every staff of this number on this line */
3402 for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
3403 if (mll_p->str == S_STAFF) {
3404 staff_p = mll_p->u.staff_p;
3405 if (staff_p->staffno == s) {
3406 staff_p->visible = NO;
3415 * Name: getmultinum()
3417 * Abstract: Find number of measures in the next staff's multirest.
3419 * Returns: The number, or 0 if next staff is not a multirest.
3421 * Description: This function is given an MLL struct, and if it's not a STAFF,
3422 * searches forward to the next STAFF. It returns as stated above.
3428 struct MAINLL *mll_p; /* point along MLL, starts at the CLEFSIG */
3431 int basictime; /* of the first group in the first following staff */
3434 /* find the first staff after this clefsig */
3435 for ( ; mll_p != 0 && mll_p->str != S_STAFF; mll_p = mll_p->next) {
3439 /* if no staff, there is no multirest */
3444 basictime = mll_p->u.staff_p->groups_p[0]->basictime;
3445 return (basictime < -1 ? -basictime : 0);