chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / abshorz.c
CommitLineData
69695f33
MW
1/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */
2/* All rights reserved */
3/*
4 * Name: abshorz.c
5 *
6 * Description: This file contains functions for setting absolute
7 * horizontal coordinates.
8 */
9
10#include <string.h>
11#include "defines.h"
12#include "structs.h"
13#include "globals.h"
14
15static void barclefsigs P((void));
16static int barwithssv P((struct MAINLL *mainll_p));
17static void setclefsigwid P((struct MAINLL *mainll_p, struct CHHEAD *chhead_p));
18static void abschunk P((struct MAINLL *mainll_p, struct MAINLL *end_p));
19static void tryabs P((struct MAINLL *mainll_p, double scale, int *scores_p,
20 short measinscore[]));
21static int endchunk P((struct MAINLL *mainll_p));
22static double adjust_measwid4mrpt P((double oldmeaswid, struct CHORD *ch_p));
23static void fillclefsig P((struct CLEFSIG *clefsig_p, struct MAINLL *feed_p));
24static struct MAINLL *trymeasure P((struct MAINLL *mainll_p, double scale,
25 float *measwidth_p, float *adjust_p, int *ressv_p));
26static void setabs P((struct MAINLL *start_p, int scores, short measinscore[]));
27static void chkrestart P((struct MAINLL *start_p, struct MAINLL *end_p));
28static void setabsscore P((struct MAINLL *start_p, struct MAINLL *end_p));
29static void setabschord P((struct CHORD *ch_p, double nomx));
30static double effwidth P((struct CHORD *ch_p));
31static double bardiff P((struct MAINLL *mainll_p, struct MAINLL *end_p));
32static void fixfullmeas P((struct CHORD *ch_p, double x));
33static void restore_grpsyl_west P((void));
34static void setipw P((void));
35static void setipwgrpsyl P((struct MAINLL *mainll_p, struct GRPSYL *gs_p));
36static void setipwchord P((struct MAINLL *mainll_p));
37static void fixendings P((void));
38static void fixreh P((void));
39static void clrinhprint P((void));
40static int hidestaffs P((struct MAINLL *mainll_p, struct MAINLL *ml2_p));
41static int silent P((struct MAINLL *mainll_p, struct MAINLL *ml2_p, int s,
42 int *ressv_p));
43static int getmultinum P((struct MAINLL *mll_p));
44
45/*
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.
48 */
49#define EFF_WIDCLEFSIG(clefsig_p) \
50 ((clefsig_p)->clefsize == DFLT_SIZE ? width_clefsig(clefsig_p) : \
51 (clefsig_p)->effwidth)
52
53/*
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.
56 */
57#define CSP(clefsig_p) (((clefsig_p)->bar_p == 0 ? 2.0 : 9.0) * STDPAD)
58\f
59/*
60 * Name: abshorz()
61 *
62 * Abstract: Set absolute horizontal coordinates of everything.
63 *
64 * Returns: void
65 *
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.
71 */
72
73void
74abshorz()
75
76{
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 */
82
83
84 debug(16, "abshorz");
85 ml2_p = 0; /* prevent useless 'used before set' warning */
86
87 /*
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.
92 */
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 */
97
98 if (mainll_p == 0)
99 pfatal("main linked list has nothing but SSVs");
100
101 if (mainll_p->str != S_FEED) {
102 mainfeed_p = newMAINLLstruct(S_FEED, 0);
103 insertMAINLL(mainfeed_p, mainll_p->prev);
104 }
105
106 /* whenever a CLEFSIG is needed after a bar line, put one there */
107 barclefsigs();
108
109 /*
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().
117 */
118 /* skip anything before first FEED first */
119 for (mainll_p = Mainllhc_p; mainll_p->str != S_FEED;
120 mainll_p = mainll_p->next)
121 ;
122 for (;;) {
123 gotbar = NO;
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) {
127
128 if (end_p->str == S_BAR)
129 gotbar = YES;
130 }
131
132 if (gotbar == NO) {
133 /*
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.
137 */
138 if (end_p == 0)
139 break;
140 /*
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.
145 */
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;
151 mainll_p = end_p;
152 continue;
153 }
154
155 while (ml2_p->str == S_SSV || ml2_p->str == S_PRHEAD ||
156 ml2_p->str == S_LINE || ml2_p->str == S_CURVE)
157 ml2_p = ml2_p->prev;
158 abschunk(mainll_p, ml2_p->next);
159 if (end_p == 0)
160 break;
161 mainll_p = end_p;
162 }
163
164 /* restore west boundaries of GRPSYLs that have associated clefs */
165 restore_grpsyl_west();
166
167 /* set inches per whole ( c[INCHPERWHOLE] ) in the relevant structs */
168 setipw();
169
170 /* move endings that start at end of score to the next score */
171 fixendings();
172
173 /* move rehearsal marks at end of a score to the next score */
174 fixreh();
175
176 /* clear the inhibitprint flag on tablature staffs when appropriate */
177 clrinhprint();
178}
179\f
180/*
181 * Name: barclefsigs()
182 *
183 * Abstract: Put a CLEFSIG after each bar line that requires one.
184 *
185 * Returns: void
186 *
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
191 * that is a restart.
192 */
193
194static void
195barclefsigs()
196
197{
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 */
226
227
228 debug(16, "barclefsigs");
229 initstructs(); /* clean out old SSV info */
230
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;
236 }
237
238 chhead_p = 0; /* keep lint happy; will be set before used */
239
240 /*
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.
244 */
245 for (;;) {
246 /*
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.
251 */
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) {
257 case S_CHHEAD:
258 /* remember the last chhead */
259 chhead_p = mainll_p->u.chhead_p;
260 break;
261 case S_SSV:
262 /* apply SSVs */
263 asgnssv(mainll_p->u.ssv_p);
264 break;
265 }
266 mainll_p = mainll_p->next;
267 }
268 if (mainll_p == 0) {
269 break;
270 }
271 bar_p = mainll_p->u.bar_p;
272
273 /*
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.
281 */
282 tssv_p = bar_p->timedssv_p;
283 gottimedssv = tssv_p != 0; /* remember if we had any */
284 if (gottimedssv) {
285 /* get clef state before the timed SSVs */
286 for (s = 1; s <= Score.staffs; s++) {
287 premidclef[s] = svpath(s, CLEF)->clef;
288 }
289 /* assign the timed SSVs */
290 for ( ; tssv_p != 0; tssv_p = tssv_p->next) {
291 asgnssv(&tssv_p->ssv);
292 }
293 }
294
295 /*
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
300 * the score).
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.
305 */
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])
315 oldclefsequal = NO;
316 if (s > 1 && oldkey[s - 1] != oldkey[s])
317 oldkeysequal = NO;
318 }
319 oldstaffs = Score.staffs;
320 strcpy(oldtimerep, Score.timerep);
321
322 /* see if clefs need printing due to timed SSVs */
323 if (gottimedssv) {
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) {
330 ;
331 }
332 /* don't force clefsig for an invisible staff*/
333 if (mll_p->u.staff_p->visible == NO) {
334 continue;
335 }
336 /*
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.
342 */
343 lastclef = premidclef[s];
344 lastclefoffset = rneg(One);
345 for (vidx = 0; vidx < MAXVOICES; vidx++) {
346 /* look down this voice */
347 offset = Zero;
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;
354 }
355 offset = radd(offset,
356 gs_p->fulltime);
357 }
358 }
359 /*
360 * Set the oldclef to the last one printed.
361 * Then later code will create a CLEFSIG, if
362 * necessary.
363 */
364 oldclef[s] = lastclef;
365 }
366 }
367
368 /*
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.
373 */
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;
378 }
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. */
381 mll_p = mainll_p;
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);
387 }
388 mll_p = mll_p->next;
389 }
390 if (mainll_p == 0)
391 break;
392
393
394 /*
395 * Get the new clefs and effective keys.
396 * Again, find out if the clefs and keys are equal on all
397 * staffs.
398 */
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])
407 newclefsequal = NO;
408 if (s > 1 && newkey[s - 1] != newkey[s])
409 newkeysequal = NO;
410 }
411
412 /* first check if any time sig info changed */
413 if (strcmp(Score.timerep, oldtimerep) != 0)
414 timechg = YES;
415 else
416 timechg = NO;
417
418 /*
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.
423 */
424 if (bar_p->bartype == RESTART) {
425 /*
426 * We always require a CLEFSIG. Allocate one and put
427 * it between where we are now and the preceding
428 * structure.
429 */
430 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
431 insertMAINLL(maincs_p, mainll_p->prev);
432 clefsig_p = maincs_p->u.clefsig_p;
433
434 clefsig_p->clefsize = DFLT_SIZE; /* full size */
435 clefsig_p->multinum = getmultinum(maincs_p);
436
437 /*
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.
442 */
443 for (s = 1; s <= oldstaffs; s++) {
444 /* draw nothing if this staff is not "normal" */
445 if (oldnorm[s] == NO || newnorm[s] == NO)
446 continue;
447 clefsig_p->prclef[s] = YES;
448 clefsig_p->sharps[s] = newkey[s];
449 }
450
451 /* print the time signature if it changed */
452 clefsig_p->prtimesig = timechg;
453
454 continue;
455 }
456
457 /*
458 * When the number of staffs changes, special rules apply.
459 * Handle this situation and continue.
460 */
461 if (oldstaffs != Score.staffs) {
462 /*
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.
473 */
474 if (timechg == NO &&
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 */
482 continue;
483 }
484
485 /*
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.
489 */
490 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
491 insertMAINLL(maincs_p, mainll_p->prev);
492 clefsig_p = maincs_p->u.clefsig_p;
493
494 /* any clefs to be printed should be small size */
495 clefsig_p->clefsize = SMALLSIZE;
496 clefsig_p->multinum = getmultinum(maincs_p);
497
498 /*
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
506 * ones.
507 */
508 for (s = 1; s <= oldstaffs; s++) {
509
510 /* draw nothing if this staff is not "normal" */
511 if (oldnorm[s] == NO || newnorm[s] == NO)
512 continue;
513 /*
514 * Draw the new clef if the clefs on each score
515 * are consistent and they changed.
516 */
517 if (oldclefsequal && newclefsequal &&
518 oldclef[1] != newclef[1])
519 clefsig_p->prclef[s] = YES;
520
521 /*
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.
525 */
526 if (oldkeysequal && newkeysequal &&
527 oldkey[1] != newkey[1]) {
528 clefsig_p->sharps[s] = newkey[1];
529
530 if (newkey[1] == 0) {
531 clefsig_p->naturals[s] =
532 oldkey[1];
533 } else if (svpath(s, CANCELKEY)->
534 cancelkey == YES) {
535 if (oldkey[1] * newkey[1] < 0) {
536 /* 1 has #s, 1 has &s */
537 clefsig_p->naturals[s] =
538 oldkey[1];
539 } else if (abs(oldkey[1]) >
540 abs(newkey[1])){
541 /* new has fewer accs*/
542 clefsig_p->naturals[s] =
543 oldkey[1] - newkey[1];
544 }
545 }
546 }
547 }
548
549 /* print the time signature if it changed */
550 if (timechg == YES)
551 clefsig_p->prtimesig = YES;
552
553 /* set clefsig's effective width */
554 setclefsigwid(maincs_p, chhead_p);
555
556 continue;
557 }
558
559
560 change = timechg;
561
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)
566 continue;
567 if (oldclef[s] != newclef[s])
568 change = YES;
569 if (oldkey[s] != newkey[s])
570 change = YES;
571 if (change == YES)
572 break; /* don't waste any more time looping */
573 }
574 if (change == NO)
575 continue; /* no visible time, key, clef changed*/
576
577 /*
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.
582 */
583 maincs_p = newMAINLLstruct(S_CLEFSIG, 0);
584 insertMAINLL(maincs_p, mainll_p->prev);
585 clefsig_p = maincs_p->u.clefsig_p;
586
587 /* any clefs to be printed should be small size */
588 clefsig_p->clefsize = SMALLSIZE;
589 clefsig_p->multinum = getmultinum(maincs_p);
590
591 /*
592 * Loop through the staffs, marking in the CLEFSIG what should
593 * be drawn.
594 */
595 for (s = 1; s <= Score.staffs; s++) {
596 /* draw nothing if this staff is invisible */
597 if (oldvis[s] == NO)
598 continue;
599
600 /* draw nothing if this staff is not "normal" */
601 if (oldnorm[s] == NO || newnorm[s] == NO)
602 continue;
603
604 /* draw the new clef if the clef changed */
605 if (oldclef[s] != newclef[s])
606 clefsig_p->prclef[s] = YES;
607
608 /*
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.
616 */
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)->
622 cancelkey == YES) {
623 if (oldkey[s] * newkey[s] < 0) {
624 /* 1 has sharps, 1 has flats */
625 clefsig_p->naturals[s] =
626 oldkey[s];
627 } else if (abs(oldkey[s]) >
628 abs(newkey[s])) {
629 /* new has fewer accidentals */
630 clefsig_p->naturals[s] =
631 oldkey[s] - newkey[s];
632 }
633 }
634 }
635 }
636
637 /*
638 * Finally, print the time signature if it changed.
639 */
640 if (timechg == YES)
641 clefsig_p->prtimesig = YES;
642
643 /* set clefsig's effective width, and widestclef */
644 setclefsigwid(maincs_p, chhead_p);
645 }
646}
647\f
648/*
649 * Name: barwithssv()
650 *
651 * Abstract: Is this bar followed by SSV(s), ignoring FEEDs and BLOCKHEADs?
652 *
653 * Returns: YES or NO
654 *
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.
658 */
659
660static int
661barwithssv(mainll_p)
662
663struct MAINLL *mainll_p; /* for the BAR */
664
665{
666 struct MAINLL *mll_p; /* loop after the BAR */
667
668
669 for (mll_p = mainll_p->next; mll_p != 0; mll_p = mll_p->next) {
670 switch (mll_p->str) {
671 case S_SSV:
672 return (YES);
673 case S_FEED:
674 case S_BLOCKHEAD:
675 break; /* ignore these, keep looking */
676 default:
677 return (NO);
678 }
679 }
680
681 return (NO); /* hit end of MLL */
682}
683\f
684/*
685 * Name: setclefsigwid()
686 *
687 * Abstract: Set effective width and widest clef of a user requested clefsig.
688 *
689 * Returns: void
690 *
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
699 * abshorz.c.
700 */
701
702static void
703setclefsigwid(mainll_p, chhead_p)
704
705struct MAINLL *mainll_p; /* point at the given clefsig's MLL struct */
706struct CHHEAD *chhead_p; /* point at the preceding chhead */
707
708{
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 */
725
726
727 debug(16, "setclefsigwid");
728
729 clefsig_p = mainll_p->u.clefsig_p; /* convenient pointer */
730
731 /*
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.
738 */
739 for (ch_p = chhead_p->ch_p; ch_p->ch_p != 0; ch_p = ch_p->ch_p)
740 ;
741 lasteast = ch_p->c[AE];
742
743 /*
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.
748 */
749 clefspace = 0.0;
750
751 widestclef = 0.0; /* max width of any clef to be printed */
752
753 size = 3.0/4.0 * DFLT_SIZE; /* small size clefs */
754
755 /*
756 * Loop backwards through the preceding measure, looking for visible
757 * staffs to process.
758 */
759 for (m2_p = mainll_p; m2_p->str != S_CHHEAD; m2_p = m2_p->prev) {
760
761 if (m2_p->str != S_STAFF || m2_p->u.staff_p->visible == NO)
762 continue;
763
764 staff_p = m2_p->u.staff_p;
765 staffno = staff_p->staffno;
766
767 /* if no clef, it doesn't need any space */
768 if (clefsig_p->prclef[staffno] == NO)
769 continue;
770
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;
775
776 /* remember biggest clef width */
777 if (clefwid > widestclef)
778 widestclef = clefwid;
779
780 /* loop through all voices on this staff */
781 for (v = 0; v < MAXVOICES; v++) {
782
783 /* find last group in this voice */
784 gs_p = staff_p->groups_p[v];
785 if (gs_p == 0)
786 continue;
787 for ( ; gs_p->next != 0; gs_p = gs_p->next)
788 ;
789
790 /*
791 * Find out what chord this group belongs to, by
792 * searching down the GRPSYL list hanging off each
793 * chord in this measure.
794 */
795 for (ch_p = chhead_p->ch_p; ch_p != 0;
796 ch_p = ch_p->ch_p) {
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 >
801 gs_p->staffno)
802 break;
803 }
804
805 /*
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.
810 */
811 if (gs2_p == gs_p) {
812 gap = lasteast -
813 (ch_p->c[AX] + gs_p->c[RE]);
814
815 if (clefwid - gap > clefspace)
816 clefspace = clefwid - gap;
817
818 break; /* look no more */
819 }
820 }
821 } /* loop through voices on a staff */
822 } /* loop through staffs */
823
824 clefsig_p->widestclef = widestclef;
825
826 /* (effective width) = (real width) - (what can overlap) */
827 clefsig_p->effwidth = width_clefsig(clefsig_p) -
828 (widestclef - clefspace);
829}
830\f
831/*
832 * Name: abschunk()
833 *
834 * Abstract: Set the absolute horz. coords of everything in one chunk.
835 *
836 * Returns: void
837 *
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.
845 */
846
847static void
848abschunk(start_p, end_p)
849
850struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
851struct MAINLL *end_p; /* points after last struct in chunk (or 0) */
852
853{
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 */
868
869
870 debug(16, "abschunk file=%s line=%d", start_p->inputfile,
871 start_p->inputlineno);
872
873 /*
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.
876 */
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);
883 }
884
885 packfact = Score.packfact; /* use current value (start of score) */
886 totwidth = 0; /* start totals at 0 */
887 totpseudodur = 0;
888 numbars = 0;
889
890 /* loop through chunk, adding up width and time */
891 for ( ; mainll_p != end_p; mainll_p = mainll_p->next) {
892
893 switch (mainll_p->str) {
894 case S_SSV:
895 /* assign to keep time sig accurate */
896 asgnssv(mainll_p->u.ssv_p);
897 break;
898
899 case S_CHHEAD:
900 /*
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
911 * point.)
912 */
913 measwidth = 0;
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;
918 }
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;
925 }
926 /* add this measure into the total */
927 totwidth += adjust_measwid4mrpt(measwidth,
928 mainll_p->u.chhead_p->ch_p);
929 break;
930
931 case S_CLEFSIG:
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);
935 break;
936
937 case S_BAR:
938 /* add width of bar line, and incr no. of bars */
939 totwidth += width_barline(mainll_p->u.bar_p);
940 numbars++;
941 break;
942 }
943 }
944
945 /*
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.
950 */
951 MALLOCA(short, measinscore, numbars + 1);
952
953 /*
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
958 * out nicely.
959 */
960 lowscale = packfact * totwidth / totpseudodur;
961 tryabs(start_p, lowscale, &scores, measinscore);
962
963 /*
964 * If the whole chunk fits on one score, just set the absolute coords
965 * for this score and get out.
966 */
967 if (scores == 1) {
968 setabs(start_p, scores, measinscore);
969 FREE(measinscore);
970 return;
971 }
972
973 /*
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".
978 *
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
982 * score.
983 */
984 reqscores = scores;
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 */
992 lowscale = midscale;
993 }
994 }
995 /*
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.
998 */
999 if (midscale != lowscale) {
1000 tryabs(start_p, lowscale, &scores, measinscore);
1001 }
1002
1003 setabs(start_p, scores, measinscore);
1004
1005 FREE(measinscore);
1006}
1007\f
1008/*
1009 * Name: tryabs()
1010 *
1011 * Abstract: Given trial scale, find how many scores are needed, etc.
1012 *
1013 * Returns: void
1014 *
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.
1018 */
1019
1020static void
1021tryabs(start_p, scale, scores_p, measinscore)
1022
1023struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
1024double scale; /* inches per "whole" unit of time */
1025int *scores_p; /* return number of scores needed */
1026short measinscore[]; /* return number of measures in each score */
1027
1028{
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?*/
1041
1042
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);
1047
1048 mainll_p = start_p;
1049
1050 /*
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.).
1054 */
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);
1060 measinscore[0] = 0;
1061
1062 /*
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.
1066 */
1067 userdelta = eff_rightmargin(start_p->next) -
1068 eff_rightmargin((struct MAINLL *)0);
1069
1070 prevfeed_p = start_p; /* init previous FEED to the start of chunk */
1071
1072 /*
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.
1079 */
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);
1085
1086 /* loop through chunk, once per measure, finding where FEEDs would go*/
1087 for (;;) {
1088 /* get width of this measure, and where next one starts */
1089 new_p = trymeasure(mainll_p, scale, &measwidth, &adjust,&ressv);
1090
1091 atend = endchunk(new_p); /* last measure of chunk? */
1092
1093 if (!atend && (measwidth - adjust) <= remwidth ||
1094 atend && (measwidth - adjust) <= remwidth - userdelta ||
1095 measinscore[*scores_p] == 0) {
1096 /*
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.
1104 */
1105 remwidth -= measwidth;
1106 measinscore[*scores_p]++;
1107 mainll_p = new_p;
1108
1109 /* if we are at the end, inc no. of scores & return */
1110 if (atend) {
1111 (*scores_p)++;
1112 return;
1113 }
1114 } else {
1115 /*
1116 * There is not room for this measure on this score.
1117 * Increment the number of scores needed.
1118 */
1119 (*scores_p)++;
1120
1121 /*
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.
1127 */
1128 if (ressv) {
1129 setssvstate(mainll_p);
1130 }
1131
1132 /*
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.
1137 */
1138 remwidth = PGWIDTH - eff_rightmargin((struct MAINLL *)0)
1139 - eff_leftmargin((struct MAINLL *)0);
1140 remwidth -= pwidth_left_of_score(mainll_p, prevfeed_p);
1141
1142 prevfeed_p = mainll_p; /* where feed would go */
1143
1144 /*
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.
1153 */
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 */
1160
1161 /*
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
1170 * measure.
1171 *
1172 * If the measure fits, don't do any of this. Just let
1173 * trymeasure figure the same one over again, next
1174 * time around.
1175 */
1176 if (!atend && measwidth > remwidth ||
1177 atend && measwidth > remwidth - userdelta) {
1178 if (ressv) {
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);
1183 }
1184 }
1185 remwidth = 0;
1186 measinscore[*scores_p] = 1;
1187 mainll_p = new_p;
1188
1189 /* if at the end, fix no. of scores & ret */
1190 if (atend) {
1191 (*scores_p)++;
1192 return;
1193 }
1194 }
1195 }
1196 }
1197}
1198\f
1199/*
1200 * Name: endchunk()
1201 *
1202 * Abstract: Is this MLL item near the end of a chunk?
1203 *
1204 * Returns: YES or NO
1205 *
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.
1211 */
1212
1213static int
1214endchunk(mainll_p)
1215
1216struct MAINLL *mainll_p; /* points into the MAINLL */
1217
1218{
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;
1225
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)
1228 return (YES);
1229 return (NO);
1230}
1231\f
1232/*
1233 * Name: adjust_measwid4mrpt()
1234 *
1235 * Abstract: If the measure contains a mrpt, adjust the measure's width.
1236 *
1237 * Returns: the new (possibly increased) measure width
1238 *
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.
1243 */
1244
1245static double
1246adjust_measwid4mrpt(oldmeaswid, ch_p)
1247
1248double oldmeaswid; /* old measure width */
1249struct CHORD *ch_p; /* points at a chord, should be first chord in meas */
1250
1251{
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? */
1257
1258
1259 /*
1260 * Scan down the first chord and see if any groups have an mrpt.
1261 */
1262 gotmrpt = NO;
1263 newmeaswid = 0.0;
1264 for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
1265 if (is_mrpt(gs_p)) {
1266 gotmrpt = YES;
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 +
1270 gs_p->padding;
1271 if (thismrpt > newmeaswid) {
1272 newmeaswid = thismrpt;
1273 }
1274 }
1275 }
1276
1277 if (gotmrpt == NO)
1278 return (oldmeaswid); /* no mrpt, return original width */
1279
1280 /* if measure is already wider than all mrpts, return unchanged */
1281 if (oldmeaswid >= newmeaswid)
1282 return (oldmeaswid);
1283
1284 /*
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.
1290 */
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;
1297 } else {
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;
1302 }
1303
1304 return (newmeaswid);
1305}
1306\f
1307/*
1308 * Name: fillclefsig()
1309 *
1310 * Abstract: Fill the CLEFSIG for after a FEED.
1311 *
1312 * Returns: void
1313 *
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();
1322 * bar_p != 0.
1323 */
1324
1325static void
1326fillclefsig(clefsig_p, feed_p)
1327
1328struct CLEFSIG *clefsig_p; /* points at empty clefsig to be filled in */
1329struct MAINLL *feed_p; /* points at a FEED in the MAINLL */
1330
1331{
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 */
1336
1337
1338 /*
1339 * On every visible staff, the clef and key signature are to
1340 * be printed.
1341 */
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);
1347 }
1348
1349 /* clefs to be printed should be regular size */
1350 clefsig_p->clefsize = DFLT_SIZE;
1351
1352 /*
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
1356 * measure.
1357 */
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)
1361 ;
1362
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;
1370
1371 /*
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.
1374 */
1375 for (mainll_p = feed_p->prev; mainll_p != 0 && mainll_p->str != S_BAR;
1376 mainll_p = mainll_p->prev)
1377 ;
1378
1379 if (clefsig_p->bar_p != 0) {
1380 /*
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.
1389 */
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;
1394 } else {
1395 clefsig_p->bar_p->bartype = INVISBAR;
1396 }
1397 } else {
1398 /*
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
1405 * was before.
1406 */
1407 CALLOC(BAR, clefsig_p->bar_p, 1);
1408
1409 if (mainll_p != 0 &&
1410 (mainll_p->u.bar_p->bartype == REPEATSTART ||
1411 mainll_p->u.bar_p->bartype == REPEATBOTH)) {
1412
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;
1427 } else {
1428 clefsig_p->bar_p->bartype = INVISBAR;
1429 }
1430 }
1431}
1432\f
1433/*
1434 * Name: trymeasure()
1435 *
1436 * Abstract: Find trial width of a measure.
1437 *
1438 * Returns: Pointer to the first MAINLL structure of the next measure,
1439 * or 0 if we hit the end of MAINLL.
1440 *
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.
1444 */
1445
1446static struct MAINLL *
1447trymeasure(mainll_p, scale, measwidth_p, adjust_p, ressv_p)
1448
1449struct MAINLL *mainll_p; /* points first thing in meas, or FEED */
1450double scale; /* inches per "whole" unit of time */
1451float *measwidth_p; /* width of measure to be filled in */
1452float *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 */
1455int *ressv_p; /* did we apply a CLEFSIG-causing SSV? */
1456
1457{
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*/
1461
1462
1463 if (mainll_p == 0)
1464 pfatal("invalid mainll_p argument (0) to trymeasure");
1465
1466 *ressv_p = NO; /* assume no SSVs for now */
1467
1468 /* every measure has one CHHEAD; find it */
1469 while (mainll_p != 0 && mainll_p->str != S_CHHEAD)
1470 mainll_p = mainll_p->next;
1471 if (mainll_p == 0)
1472 pfatal("missing CHHEAD near end of main linked list");
1473
1474 *measwidth_p = 0;
1475
1476 /*
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.
1480 */
1481 for (ch_p = mainll_p->u.chhead_p->ch_p; ch_p != 0;
1482 ch_p = ch_p->ch_p) {
1483
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)
1488 idealwidth = 0;
1489 *measwidth_p += MAX(idealwidth, ch_p->width);
1490 }
1491
1492 /*
1493 * Find the bar line and add in its width.
1494 */
1495 while (mainll_p->str != S_BAR)
1496 mainll_p = mainll_p->next;
1497 *measwidth_p += width_barline(mainll_p->u.bar_p);
1498
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 */
1504 }
1505
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);
1508
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))
1513 return (mainll_p);
1514
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 */
1520 }
1521
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;
1526 }
1527
1528 return (mainll_p);
1529}
1530\f
1531/*
1532 * Name: setabs()
1533 *
1534 * Abstract: Sets horizontal absolute coordinates for one chunk.
1535 *
1536 * Returns: void
1537 *
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.
1542 */
1543
1544static void
1545setabs(start_p, scores, measinscore)
1546
1547struct MAINLL *start_p; /* FEED at start of chunk of MAINLL */
1548int scores; /* number of scores this chunk needs */
1549short measinscore[]; /* number of measures in each score */
1550
1551{
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 */
1556
1557
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);
1562
1563 /* point at first item in first measure of chunk (skip initial FEED) */
1564 mainll_p = start_p->next;
1565
1566 for (score = 0; score < scores; score++) {
1567 /* the first score already has a FEED; insert if later score */
1568 if (score != 0) {
1569 ml2_p = newMAINLLstruct(S_FEED, 0);
1570 insertMAINLL(ml2_p, mainll_p->prev);
1571 }
1572 mainll_p = mainll_p->prev; /* point at the FEED */
1573
1574 /*
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.
1580 */
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);
1585
1586 /*
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.
1591 */
1592 ml2_p = ml2_p->next; /* point at CHHEAD */
1593 for (n = 0; n < measinscore[score]; n++) {
1594 do {
1595 ml2_p = ml2_p->next;
1596 } while (ml2_p != 0 && ml2_p->str != S_CHHEAD &&
1597 ml2_p->str != S_BLOCKHEAD);
1598 }
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
1603 * effect */
1604 setssvstate(start_p);
1605 }
1606 setabsscore(mainll_p, ml2_p);
1607 mainll_p = ml2_p;
1608 }
1609}
1610\f
1611/*
1612 * Name: chkrestart()
1613 *
1614 * Abstract: Check for restart bars and remove if necessary.
1615 *
1616 * Returns: void
1617 *
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.
1623 */
1624
1625static void
1626chkrestart(start_p, end_p)
1627
1628struct MAINLL *start_p; /* point at the initial FEED of this score */
1629struct MAINLL *end_p; /* point after the last thing on this score */
1630
1631{
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 */
1635
1636
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)
1640 ;
1641
1642 if (mainll_p->u.bar_p->bartype == RESTART) {
1643 /*
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.
1652 */
1653 mainll_p->u.bar_p->bartype = INVISBAR;
1654 mainll_p->u.bar_p->padding = -0.12;
1655
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 */
1661 }
1662 }
1663
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)
1668 m2_p = mainll_p;
1669 }
1670
1671 if (m2_p->u.bar_p->bartype == RESTART) {
1672 /*
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.
1679 */
1680 m2_p->u.bar_p->bartype = INVISBAR;
1681 m2_p->u.bar_p->padding = 0;
1682
1683 mainll_p = m2_p; /* remember bar */
1684
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)
1687 ;
1688 if (m2_p == 0)
1689 pfatal("the last bar in the piece is a restart");
1690
1691 /*
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.
1697 */
1698 if (m2_p->u.clefsig_p->prtimesig == YES) {
1699 mainll_p->u.bar_p->c[AY] = 1.0;
1700 }
1701
1702 m2_p->prev->next = m2_p->next;
1703 m2_p->next->prev = m2_p->prev;
1704 FREE(m2_p->u.clefsig_p);
1705 FREE(m2_p);
1706 }
1707}
1708\f
1709/*
1710 * Name: setabsscore()
1711 *
1712 * Abstract: Sets horizontal absolute coordinates for one score.
1713 *
1714 * Returns: void
1715 *
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.
1719 */
1720
1721static void
1722setabsscore(start_p, end_p)
1723
1724struct MAINLL *start_p; /* point at the initial FEED of this score */
1725struct MAINLL *end_p; /* point after the last thing on this score */
1726
1727{
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 */
1754
1755
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 */
1761
1762 /*
1763 * Get total available width on this score.
1764 */
1765 if (end_p == 0) {
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)
1769 ;
1770 if (m2_p->str == S_FEED) {
1771 /* a feed after the last bar; use it */
1772 eff_right = eff_rightmargin(m2_p);
1773 } else {
1774 /* no feed after the last bar */
1775 eff_right = eff_rightmargin((struct MAINLL *)0);
1776 }
1777 } else {
1778 /*
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.)
1782 */
1783 if (end_p->prev->str == S_FEED) {
1784 /* it is a feed, so use it */
1785 eff_right = eff_rightmargin(end_p->prev);
1786 } else {
1787 /* no feed */
1788 eff_right = eff_rightmargin((struct MAINLL *)0);
1789 }
1790 }
1791
1792 scorewidth = PGWIDTH - eff_right - eff_leftmargin(start_p);
1793 scorewidth -= width_left_of_score(start_p);
1794
1795 /*
1796 * Accumulate the total minimum width, total pseudodur in equivalent
1797 * wholes, and the total minimum width needed by chords.
1798 */
1799 totwidth = 0;
1800 totwhole = 0;
1801 chw = 0;
1802 for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next){
1803 switch (mainll_p->str) {
1804
1805 case S_SSV:
1806 /* assign to keep time sig accurate */
1807 asgnssv(mainll_p->u.ssv_p);
1808 break;
1809
1810 case S_CHHEAD:
1811 /*
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
1818 * any.
1819 */
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)
1822 ;
1823 if (ch_p == 0)
1824 break;
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);
1829
1830 /* count time only if not a chord of */
1831 /* compressible, nonpadded spaces */
1832 if (ch_p->width != 0)
1833 totwhole += ch_p->pseudodur;
1834 }
1835 break;
1836
1837 case S_CLEFSIG:
1838 /*
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
1843 * this clefsig.
1844 */
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;
1848 m2_p = m2_p->prev)
1849 ;
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;
1853 }
1854 }
1855
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);
1862 break;
1863
1864 case S_BAR:
1865 /* bar's width */
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);
1872 }
1873 lastbarmll_p = mainll_p;
1874 break;
1875 }
1876 }
1877
1878 /*
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.
1882 */
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) {
1885 break;
1886 }
1887 }
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);
1892 } else {
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) {
1897 int s;
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) {
1902 break;
1903 }
1904 }
1905 if (s > MAXSTAFFS) {
1906 totwidth -= eos_bar_adjust(
1907 lastbarmll_p->u.bar_p);
1908 }
1909 }
1910 }
1911
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);
1918 } else {
1919 l_ufatal(start_p->inputfile, start_p->inputlineno,
1920 "too much (%f cm) to put in score",
1921 totwidth * Score.scale_factor *
1922 CMPERINCH);
1923 }
1924 }
1925
1926 /*
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.
1931 */
1932 notespace = scorewidth - (totwidth - chw);
1933
1934 /*
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.
1943 */
1944 ntotwhole = totwhole; /* initially assume all may be expandable */
1945 nnotespace = notespace;
1946 ntoowide = 0;
1947 do {
1948 /*
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.
1956 *
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.
1959 */
1960 if (totwhole == 0.0) {
1961 inchpwhole = 1.0;
1962 break;
1963 }
1964 /*
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.
1968 */
1969 inchpwhole = nnotespace / ntotwhole;
1970
1971 /* start with all chords' time and space */
1972 ntotwhole = totwhole;
1973 nnotespace = notespace;
1974
1975 toowide = ntoowide; /* remember how many last time */
1976 ntoowide = 0;
1977
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) {
1981
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);
1990 ntoowide++;
1991 }
1992 }
1993 }
1994 }
1995
1996 /*
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.
2000 */
2001 if (ntotwhole <= 0)
2002 break;
2003
2004 } while (ntoowide > toowide);
2005
2006 /*
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.
2010 */
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) {
2015
2016 /* normal case (proportional) */
2017 expanded = ch_p->pseudodur * inchpwhole;
2018
2019 /* special case to fix space interaction */
2020
2021 /* but a chord of all compressible, */
2022 /* nonpadded spaces deserves no width */
2023 if (ch_p->width == 0)
2024 expanded = 0;
2025
2026 /* get min dist needed from our X to next's X */
2027 eff = effwidth(ch_p);
2028
2029 /* the dist we'll really have from X to X */
2030 ch_p->fullwidth = MAX(eff, expanded);
2031 }
2032 }
2033 }
2034
2035 /*
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.
2041 */
2042 /* first reset SSVs to how they were at start of this score */
2043 setssvstate(start_p);
2044
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 */
2050
2051 for (mainll_p = start_p; mainll_p != end_p; mainll_p = mainll_p->next) {
2052 switch (mainll_p->str) {
2053 case S_SSV:
2054 /* assign to keep time sig accurate */
2055 asgnssv(mainll_p->u.ssv_p);
2056 break;
2057
2058 case S_CLEFSIG:
2059 clefsig_p = mainll_p->u.clefsig_p;
2060
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 +
2068 CSP(clefsig_p);
2069 leftx = absx;
2070 break;
2071 }
2072
2073 /* "beginning of line" or "restart" clefsig */
2074 clefsig_p->wclefsiga = absx;
2075 if (clefsig_p->hide == NO) {
2076 absx += width_clefsig(clefsig_p) +
2077 CSP(clefsig_p);
2078 }
2079 bar_p = clefsig_p->bar_p;
2080 if (bar_p != 0) {
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;
2085
2086 /* remember the AE of this pseudobar */
2087 prevbarae = absx;
2088 }
2089 leftx = absx;
2090 break;
2091
2092 case S_BAR:
2093 bar_p = mainll_p->u.bar_p;
2094 absx += bar_p->padding;
2095
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);
2100 }
2101
2102 /*
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.
2107 */
2108 for (m2_p = mainll_p; m2_p != 0 &&
2109 m2_p->str != S_CLEFSIG &&
2110 m2_p->str != S_CHHEAD;
2111 m2_p = m2_p->next)
2112 ;
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;
2118
2119 /*
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.
2125 */
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);
2130 }
2131 }
2132 wid = width_clefsig(clefsig_p);
2133 setssvstate(mainll_p);
2134
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);
2140
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 */
2147 }
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 */
2154
2155 /*
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.
2159 */
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;
2167 }
2168 }
2169
2170 /* remember the AE of this bar */
2171 prevbarae = absx;
2172 break;
2173
2174 case S_STAFF:
2175 /* as we come to each staff, set AW to prev bar's AE */
2176 mainll_p->u.staff_p->c[AW] = prevbarae;
2177 break;
2178
2179 case S_CHHEAD:
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)
2184 break;
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;
2189 }
2190 break;
2191 }
2192 }
2193}
2194\f
2195/*
2196 * Name: setabschord()
2197 *
2198 * Abstract: Sets horizontal absolute coordinates for everything in a chord.
2199 *
2200 * Returns: void
2201 *
2202 * Description: This function, given a chord, and its absolute offset, sets
2203 * the horizontal absolute coordinates of everything in it.
2204 */
2205
2206static void
2207setabschord(ch_p, nomx)
2208
2209struct CHORD *ch_p; /* point at the chord */
2210double nomx; /* nominal X coord; may shift it right a bit */
2211
2212{
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 */
2217
2218
2219 /*
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.
2224 */
2225 if ((extra = ch_p->fullwidth - effwidth(ch_p)) > 0) {
2226 nomx += (extra > 1.20 ? 0.20 : extra / 6);
2227 }
2228
2229 ch_p->c[AX] = nomx;
2230 ch_p->c[AW] = nomx + ch_p->c[RW];
2231 ch_p->c[AE] = nomx + ch_p->c[RE];
2232
2233 /*
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.
2238 */
2239 for (gs_p = ch_p->gs_p; gs_p != 0; gs_p = gs_p->gs_p) {
2240 /*
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.
2243 */
2244 if (gs_p->grpsyl == GS_GROUP) {
2245 g_p = gs_p; /* init to the normal group */
2246 do {
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];
2251
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];
2260 }
2261 g_p = g_p->prev;
2262 } while (g_p != 0 && g_p->grpvalue == GV_ZERO);
2263 } else {
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];
2268 }
2269 }
2270}
2271\f
2272/*
2273 * Name: effwidth()
2274 *
2275 * Abstract: Find "effective" width of a chord.
2276 *
2277 * Returns: the width
2278 *
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.
2282 */
2283
2284static double
2285effwidth(ch_p)
2286
2287struct CHORD *ch_p; /* point at the chord */
2288
2289{
2290 struct CHORD *next_p;
2291
2292
2293 /* compressible, nonpadded spaces count for nothing */
2294 if (ch_p->width == 0)
2295 return (0.0);
2296
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)
2301 break;
2302 }
2303
2304 /*
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.
2308 */
2309 if (next_p == 0)
2310 return (ch_p->c[RE]);
2311 else
2312 return (ch_p->c[RE] - next_p->c[RW]);
2313}
2314\f
2315/*
2316 * Name: bardiff()
2317 *
2318 * Abstract: Find size difference of end of score bar vs. what it will be.
2319 *
2320 * Returns: void
2321 *
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.
2329 */
2330
2331static double
2332bardiff(mainll_p, end_p)
2333
2334struct MAINLL *mainll_p; /* MLL for the bar line */
2335struct MAINLL *end_p; /* MLL after end of the score */
2336
2337{
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 */
2341
2342
2343 /*
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
2346 * return zero.
2347 */
2348 for (mll_p = mainll_p; mll_p != end_p; mll_p = mll_p->next) {
2349 if (mll_p->str == S_CHHEAD)
2350 return (0.0);
2351 }
2352
2353 /* last bar in the score, so do the arithmetic */
2354 switch (mainll_p->u.bar_p->bartype) {
2355 case REPEATSTART:
2356 bar.bartype = REPEATSTART;
2357 temp = width_barline(&bar);
2358 bar.bartype = SINGLEBAR;
2359 return (temp - width_barline(&bar));
2360
2361 case REPEATBOTH:
2362 bar.bartype = REPEATBOTH;
2363 temp = width_barline(&bar);
2364 bar.bartype = REPEATEND;
2365 return (temp - width_barline(&bar));
2366 }
2367
2368 return (0.0); /* all other types remain the same; difference = 0 */
2369}
2370\f
2371/*
2372 * Name: fixfullmeas()
2373 *
2374 * Abstract: Adjust the AE of full measure symbols (mr, multirest, mrpt).
2375 *
2376 * Returns: void
2377 *
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.
2389 */
2390
2391static void
2392fixfullmeas(ch_p, x)
2393
2394struct CHORD *ch_p; /* point at the chord */
2395double x; /* absolute X coord of center of measure */
2396
2397{
2398 struct GRPSYL *gs_p; /* point at a group or syllable in chord */
2399
2400
2401 /* in case we have all spaces */
2402 if (ch_p == 0)
2403 return;
2404
2405 debug(32, "fixfullmeas file=%s line=%d x=%f", ch_p->gs_p->inputfile,
2406 ch_p->gs_p->inputlineno, (float)x);
2407
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) {
2412 continue;
2413 }
2414
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;
2421 /*
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.
2426 */
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;
2432 }
2433 }
2434 gs_p->c[AE] = x + (x - gs_p->c[AW]);
2435 }
2436 }
2437
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;
2442 }
2443}
2444\f
2445/*
2446 * Name: restore_grpsyl_west()
2447 *
2448 * Abstract: Restore all GRPSYLs' west coords when there was a clef there.
2449 *
2450 * Returns: void
2451 *
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.
2457 */
2458
2459static void
2460restore_grpsyl_west()
2461
2462{
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 */
2470
2471
2472 size = 3.0/4.0 * DFLT_SIZE; /* small size clefs */
2473 initstructs();
2474
2475 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2476 switch (mainll_p->str) {
2477 case S_SSV:
2478 /* keep staffscale up to date */
2479 asgnssv(mainll_p->u.ssv_p);
2480 continue;
2481 case S_STAFF:
2482 /* break out to handle staff */
2483 break;
2484 default:
2485 continue;
2486 }
2487
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 */
2493 }
2494
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;
2501
2502 /*
2503 * If we are a grace group, look ahead to the
2504 * main group and restore it too.
2505 */
2506 if (gs_p->grpvalue == GV_ZERO) {
2507 for (gs2_p = gs_p; gs2_p->grpvalue ==
2508 GV_ZERO; gs2_p = gs2_p->next) {
2509 ;
2510 }
2511 gs2_p->c[RW] += clefwid;
2512 gs2_p->c[AW] += clefwid;
2513 }
2514 }
2515 }
2516 }
2517}
2518\f
2519/*
2520 * Name: setipw()
2521 *
2522 * Abstract: Set INCHPERWHOLE "coordinate" for all structures having it.
2523 *
2524 * Returns: void
2525 *
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.
2529 */
2530
2531static void
2532setipw()
2533
2534{
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 */
2540
2541
2542 debug(16, "setipw");
2543 initstructs(); /* clean out old SSV info */
2544
2545 /*
2546 * Loop through MLL, applying SSVs and processing each visible linked
2547 * list of GRPSYLs.
2548 */
2549 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2550
2551 switch (mainll_p->str) {
2552 case S_SSV:
2553 /* this is needed to keep time sig up to date */
2554 asgnssv(mainll_p->u.ssv_p);
2555 break;
2556
2557 case S_CHHEAD:
2558 /* set the thing for all chords in this measure */
2559 setipwchord(mainll_p);
2560 break;
2561
2562 case S_STAFF:
2563 /* skip this staff if it's invisible */
2564 if (mainll_p->u.staff_p->visible == NO)
2565 break;
2566
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);
2571 }
2572
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);
2577 }
2578
2579 break;
2580
2581 case S_BAR:
2582 /*
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.
2589 */
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[
2595 TIME] == YES) {
2596 timeden = m2_p->u.ssv_p->timeden;
2597 }
2598 }
2599 if (m2_p == 0 || m2_p->str == S_FEED)
2600 break;
2601
2602 /*
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).
2609 */
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]);
2613 break;
2614
2615 case S_CLEFSIG:
2616 /*
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.
2621 */
2622 if (mainll_p->u.clefsig_p->bar_p == 0)
2623 break;
2624
2625 if (mainll_p->next->str != S_CHHEAD)
2626 pfatal("CLEFSIG with pseudo bar not followed by CHHEAD");
2627
2628 mainll_p->u.clefsig_p->bar_p->c[INCHPERWHOLE] =
2629 Score.timeden *
2630 (mainll_p->next->u.chhead_p->ch_p->c[AX] -
2631 mainll_p->u.clefsig_p->bar_p->c[AX]);
2632 break;
2633 }
2634 }
2635}
2636\f
2637/*
2638 * Name: setipwgrpsyl()
2639 *
2640 * Abstract: Set INCHPERWHOLE "coordinate" for the GRPSYLs in one list.
2641 *
2642 * Returns: void
2643 *
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.
2647 */
2648
2649static void
2650setipwgrpsyl(mainll_p, gs_p)
2651
2652struct MAINLL *mainll_p; /* point along main linked list */
2653struct GRPSYL *gs_p; /* point along this GRPSYL list */
2654
2655{
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 */
2660
2661
2662 debug(32, "setipwgrpsyl file=%s line=%d", gs_p->inputfile,
2663 gs_p->inputlineno);
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)
2667 ;
2668 if (gs_p == 0)
2669 pfatal("nothing but grace notes in measure");
2670
2671 /*
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.
2675 */
2676 for (;;) {
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)
2682 ;
2683 if (ngs_p == 0)
2684 break;
2685
2686 /*
2687 * Distance between them divided by time gives the space a
2688 * a whole note theoretically would have been given.
2689 */
2690 inchperwhole = (ngs_p->c[AX] - gs_p->c[AX]) /
2691 RAT2FLOAT(gs_p->fulltime);
2692
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]
2698 = inchperwhole;
2699 }
2700
2701 /* point current at next, for next iteration */
2702 gs_p = ngs_p;
2703 }
2704
2705 /*
2706 * We've hit the end of the measure. Loop forward through the MLL
2707 * until we find the bar line.
2708 */
2709 for (m2_p = mainll_p;
2710 m2_p != 0 && m2_p->str != S_BAR;
2711 m2_p = m2_p->next)
2712 ;
2713 if (m2_p == 0)
2714 pfatal("no bar at end of last measure");
2715
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);
2719
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;
2724 }
2725}
2726\f
2727/*
2728 * Name: setipwchord()
2729 *
2730 * Abstract: Set INCHPERWHOLE "coordinate" for the CHORDs in one list.
2731 *
2732 * Returns: void
2733 *
2734 * Description: This function sets the special pseudocoord "c[INCHPERWHOLE]"
2735 * for all the CHORDs in the list hanging off of one CHHEAD.
2736 */
2737
2738static void
2739setipwchord(mainll_p)
2740
2741struct MAINLL *mainll_p; /* point at the CHHEAD */
2742
2743{
2744 struct MAINLL *m2_p; /* look forward for bar line */
2745 struct CHORD *ch_p, *nch_p; /* point at chords */
2746
2747
2748 debug(32, "setipwchord file=%s line=%d", mainll_p->inputfile,
2749 mainll_p->inputlineno);
2750 /*
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.
2755 */
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) {
2758 /*
2759 * Distance between them divided by time gives the space a
2760 * a whole note theoretically would have been given.
2761 */
2762 ch_p->c[INCHPERWHOLE] = (nch_p->c[AX] - ch_p->c[AX]) /
2763 RAT2FLOAT(ch_p->duration);
2764 }
2765
2766 /*
2767 * We've hit the end of the measure. Loop forward through the MLL
2768 * until we find the bar line.
2769 */
2770 for (m2_p = mainll_p;
2771 m2_p != 0 && m2_p->str != S_BAR;
2772 m2_p = m2_p->next)
2773 ;
2774 if (m2_p == 0)
2775 pfatal("no bar at end of last measure");
2776
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);
2780}
2781\f
2782/*
2783 * Name: fixendings()
2784 *
2785 * Abstract: Fix endings at end of score and in pseudobars.
2786 *
2787 * Returns: void
2788 *
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.
2793 */
2794
2795static void
2796fixendings()
2797
2798{
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 */
2803
2804
2805 debug(16, "fixendings");
2806 /*
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.)
2811 */
2812 for (mainll_p = Mainlltc_p; mainll_p != 0; mainll_p = mainll_p->prev) {
2813 if (mainll_p->str != S_BAR)
2814 continue;
2815 if (mainll_p->u.bar_p->endingloc != STARTITEM)
2816 continue;
2817
2818 /*
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
2821 * the next bar.
2822 */
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)
2825 ;
2826 if (m2_p == 0)
2827 pfatal("unterminated ending");
2828 if (m2_p->str == S_BAR)
2829 continue;
2830
2831 /*
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
2836 * real ones.
2837 */
2838 for (m2_p = mainll_p->prev; m2_p != 0 && m2_p->str != S_BAR;
2839 m2_p = m2_p->prev)
2840 ;
2841
2842 /*
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.
2847 */
2848 if (m2_p == 0 || m2_p->u.bar_p->endingloc == ENDITEM ||
2849 m2_p->u.bar_p->endingloc == NOITEM)
2850
2851 mainll_p->u.bar_p->endingloc = NOITEM;
2852 else
2853 mainll_p->u.bar_p->endingloc = ENDITEM;
2854
2855 str_p = mainll_p->u.bar_p->endinglabel;
2856 mainll_p->u.bar_p->endinglabel = 0;
2857
2858 /*
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.
2862 */
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);
2865 m2_p = m2_p->next)
2866 ;
2867 if (m2_p == 0) {
2868 pfatal("can't find any music after ending begins");
2869 }
2870 m2_p->next->u.clefsig_p->bar_p->endingloc = STARTITEM;
2871 m2_p->next->u.clefsig_p->bar_p->endinglabel = str_p;
2872 }
2873
2874 /*
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.
2878 */
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) {
2885 /*
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.)
2890 */
2891 if (bar_p != 0 && bar_p->endingloc == INITEM)
2892 mainll_p->u.clefsig_p->bar_p->endingloc
2893 = INITEM;
2894 }
2895 }
2896}
2897\f
2898/*
2899 * Name: fixreh()
2900 *
2901 * Abstract: Move rehearsal marks at end of a score to the next score.
2902 *
2903 * Returns: void
2904 *
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.
2908 */
2909
2910static void
2911fixreh()
2912
2913{
2914 struct MAINLL *mainll_p; /* point along main linked list */
2915 struct MAINLL *m2_p; /* look forward for bar line */
2916
2917
2918 debug(16, "fixreh");
2919 /*
2920 * Loop through the main linked list, looking for rehearsal marks at
2921 * the end of a score, and moving them.
2922 */
2923 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
2924 if (mainll_p->str != S_BAR)
2925 continue;
2926 if (mainll_p->u.bar_p->reh_type == REH_NONE)
2927 continue;
2928
2929 /*
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
2932 * the next bar.
2933 */
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)
2936 ;
2937 if (m2_p == 0)
2938 return; /* nothing more we can do in this case */
2939 if (m2_p->str == S_BAR)
2940 continue;
2941
2942 /*
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.
2947 */
2948 while (m2_p != 0 && ! IS_CLEFSIG_FEED(m2_p)) {
2949 m2_p = m2_p->next;
2950 }
2951 if (m2_p == 0) {
2952 return; /* there is no more music, can't move reh */
2953 }
2954
2955 /*
2956 * We found the FEED. Move the rehearsal mark to the pseudo
2957 * bar after the FEED.
2958 */
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;
2962
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;
2966
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;
2970
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;
2974 }
2975}
2976\f
2977/*
2978 * Name: clrinhprint()
2979 *
2980 * Abstract: Clear the inhibitprint on tablature staffs when appropriate.
2981 *
2982 * Returns: void
2983 *
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.
2989 */
2990
2991static void
2992clrinhprint()
2993
2994{
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 */
3000
3001
3002 debug(16, "clrinhprint");
3003 sawscorefeed = YES; /* "new score" at start of song */
3004
3005 /*
3006 * Loop through main linked list, looking for visible tablature STAFFs,
3007 * scorefeeds, and bar lines.
3008 */
3009 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
3010
3011 switch (mainll_p->str) {
3012 case S_FEED:
3013 sawscorefeed = YES; /* just saw a feed */
3014 continue;
3015 case S_BAR:
3016 sawscorefeed = NO; /* next bar, forget the feed */
3017 continue;
3018 case S_STAFF:
3019 /*
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.
3023 */
3024 if (sawscorefeed == YES &&
3025 mainll_p->u.staff_p->visible == YES &&
3026 is_tab_staff(mainll_p->u.staff_p->staffno))
3027 break;
3028 continue;
3029 default:
3030 continue;
3031 }
3032
3033 /* loop through each possible voice on tab staff */
3034 for (vidx = 0; vidx < MAXVOICES; vidx++) {
3035
3036 /* if voice doesn't exist, break out */
3037 gs_p = mainll_p->u.staff_p->groups_p[vidx];
3038 if (gs_p == 0)
3039 break;
3040
3041 /* if not a note group, there's nothing to do */
3042 if (gs_p->grpcont != GC_NOTES)
3043 continue;
3044
3045 /*
3046 * If inhibitprint was set, we need to put parens
3047 * around the notes (frets) and clear the bit.
3048 */
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;
3053 }
3054 }
3055 }
3056}
3057\f
3058/*
3059 * Name: hidestaffs()
3060 *
3061 * Abstract: Make staffs invisible if visible=whereused and they're empty.
3062 *
3063 * Returns: void
3064 *
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
3071 * invisible.
3072 */
3073
3074static int
3075hidestaffs(mainll_p, ml2_p)
3076
3077struct MAINLL *mainll_p; /* point at feed at start of score */
3078struct MAINLL *ml2_p; /* point at last thing on the score */
3079
3080{
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? */
3087
3088
3089 debug(16, "hidestaffs");
3090
3091 /*
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
3094 * ones invisible.
3095 */
3096 /* find the first (currently) visible staff in this score */
3097 firstvis = 0;
3098 for (s = 1; s <= Score.staffs; s++) {
3099 if (svpath(s, VISIBLE)->visible == YES) {
3100 firstvis = s;
3101 break;
3102 }
3103 }
3104 if (firstvis == 0) {
3105 pfatal("no visible staffs in score");
3106 }
3107
3108 /*
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.
3116 */
3117 foundvis = NO;
3118 forced_invis = NO;
3119 for (s = Score.staffs; s >= firstvis; s--) {
3120 if (s == firstvis && foundvis == NO) {
3121 /* only the top visible staff remains visible */
3122 break;
3123 }
3124 ssv_p = svpath(s, VISIBLE);
3125 if (ssv_p->visible == NO) { /* already invisible */
3126 continue;
3127 }
3128 if (ssv_p->hidesilent == YES) {
3129 if (silent(mainll_p, ml2_p, s, &ressv) == YES) {
3130 /* silent() forced it invisible */
3131 forced_invis = YES;
3132 } else {
3133 /* silent() left it visible */
3134 foundvis = YES;
3135 }
3136 if (ressv == YES) {
3137 setssvstate(mainll_p);
3138 }
3139 } else { /* hidesilent == NO */
3140 foundvis = YES; /* leave it visible */
3141 }
3142 }
3143
3144 return (forced_invis);
3145}
3146\f
3147/*
3148 * Name: silent()
3149 *
3150 * Abstract: Make a staff invisible for this score, if appropriate.
3151 *
3152 * Returns: YES if we made it invisible, else NO
3153 *
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.
3161 */
3162
3163static int
3164silent(feedmll_p, ml2_p, s, ressv_p)
3165
3166struct MAINLL *feedmll_p; /* point along main linked list */
3167struct MAINLL *ml2_p; /* point at MLL item at end of this score */
3168int s; /* staff number */
3169int *ressv_p; /* must the caller reapply SSVs? */
3170
3171{
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 */
3182
3183
3184 *ressv_p = NO; /* no SSVs have been applied yet */
3185
3186 /* find the last bar line in this score; it's where we should stop */
3187 lastbar_p = 0;
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) {
3191 lastbar_p = mll_p;
3192 }
3193 }
3194 /* if none, there is no music here */
3195 if (lastbar_p == 0) {
3196 return (NO); /* nothing to hide */
3197 }
3198
3199 /*
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
3202 * visible.
3203 */
3204 for (mll_p = feedmll_p; mll_p != lastbar_p; mll_p = mll_p->next) {
3205 switch (mll_p->str) {
3206 case S_SSV:
3207 /*
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
3211 * are doing.
3212 */
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 */
3216 continue;
3217 }
3218 if (ssv_p->used[VISIBLE] != NO) {
3219 /*
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.
3224 */
3225 asgnssv(ssv_p);
3226 *ressv_p = YES;
3227 }
3228 /*
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.
3236 */
3237 if (svpath(s, VISIBLE)->hidesilent == NO) {
3238 return (NO);
3239 }
3240 continue;
3241
3242 case S_STAFF:
3243 staff_p = mll_p->u.staff_p;
3244 if (staff_p->staffno != s) {
3245 continue; /* some other staff, ignore */
3246 }
3247 break; /* break out to handle our staff */
3248
3249 default:
3250 continue;
3251 }
3252
3253 /* decide whether this staff can be made invisible */
3254
3255 /*
3256 * Look at each group in each possible voice. If any contain
3257 * notes, our staff must remain visible.
3258 */
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) {
3263 return (NO);
3264 }
3265 }
3266 }
3267
3268 /* if there are any syllables, our staff must remain visible */
3269 if (staff_p->nsyllists != 0) {
3270 return (NO);
3271 }
3272
3273 /* if there is any stuff, our staff must remain visible */
3274 if (staff_p->stuff_p != 0) {
3275 return (NO);
3276 }
3277
3278 /*
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.
3285 */
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;
3290 vidx++) {
3291 if (pstaff_p->sylplace[vidx] ==
3292 PL_BETWEEN) {
3293 return (NO);
3294 }
3295 }
3296 for (stuff_p = pstaff_p->stuff_p; stuff_p != 0;
3297 stuff_p = stuff_p->next) {
3298 if (stuff_p->place == PL_BETWEEN) {
3299 return (NO);
3300 }
3301 }
3302 }
3303 }
3304 }
3305
3306 /*
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.
3314 */
3315
3316 /*
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.
3322 */
3323 ins_p = feedmll_p->prev;
3324 if (ins_p != 0 && ins_p->str == S_CLEFSIG) {
3325 ins_p = ins_p->prev;
3326 }
3327
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;
3332 ssv_p->staffno = s;
3333 ssv_p->used[VISIBLE] = YES;
3334 ssv_p->visible = NO;
3335 insertMAINLL(new_p, ins_p);
3336
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;
3342 ssv_p->staffno = s;
3343 ssv_p->voiceno = vidx + 1;
3344 ssv_p->used[VISIBLE] = UNSET;
3345 insertMAINLL(new_p, ins_p);
3346 }
3347
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) {
3351 continue;
3352 }
3353 ssv_p = mll_p->u.ssv_p;
3354 /*
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.
3358 */
3359 if (ssv_p->context != C_SCORE && ssv_p->staffno == s) {
3360 ssv_p->used[VISIBLE] = NO;
3361 }
3362 }
3363
3364 /* the SSVs to be put at the end go after the last bar line */
3365 ins_p = lastbar_p;
3366
3367 /*
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.
3371 */
3372 new_p = newMAINLLstruct(S_SSV, -1);
3373 ssv_p = new_p->u.ssv_p;
3374 ssv_p->context = C_STAFF;
3375 ssv_p->staffno = s;
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;
3380 } else {
3381 ssv_p->used[VISIBLE] = UNSET;
3382 }
3383 insertMAINLL(new_p, ins_p);
3384
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;
3389 ssv_p->staffno = s;
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;
3395 } else {
3396 ssv_p->used[VISIBLE] = UNSET;
3397 }
3398 insertMAINLL(new_p, ins_p);
3399 }
3400
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;
3407 }
3408 }
3409 }
3410
3411 return (YES);
3412}
3413\f
3414/*
3415 * Name: getmultinum()
3416 *
3417 * Abstract: Find number of measures in the next staff's multirest.
3418 *
3419 * Returns: The number, or 0 if next staff is not a multirest.
3420 *
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.
3423 */
3424
3425static int
3426getmultinum(mll_p)
3427
3428struct MAINLL *mll_p; /* point along MLL, starts at the CLEFSIG */
3429
3430{
3431 int basictime; /* of the first group in the first following staff */
3432
3433
3434 /* find the first staff after this clefsig */
3435 for ( ; mll_p != 0 && mll_p->str != S_STAFF; mll_p = mll_p->next) {
3436 ;
3437 }
3438
3439 /* if no staff, there is no multirest */
3440 if (mll_p == 0) {
3441 return (0);
3442 }
3443
3444 basictime = mll_p->u.staff_p->groups_p[0]->basictime;
3445 return (basictime < -1 ? -basictime : 0);
3446}