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);