chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / abshorz.c
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
15 static void barclefsigs P((void));
16 static int barwithssv P((struct MAINLL *mainll_p));
17 static void setclefsigwid P((struct MAINLL *mainll_p, struct CHHEAD *chhead_p));
18 static void abschunk P((struct MAINLL *mainll_p, struct MAINLL *end_p));
19 static void tryabs P((struct MAINLL *mainll_p, double scale, int *scores_p,
20                 short measinscore[]));
21 static int endchunk P((struct MAINLL *mainll_p));
22 static double adjust_measwid4mrpt P((double oldmeaswid, struct CHORD *ch_p));
23 static void fillclefsig P((struct CLEFSIG *clefsig_p, struct MAINLL *feed_p));
24 static struct MAINLL *trymeasure P((struct MAINLL *mainll_p, double scale,
25                 float *measwidth_p, float *adjust_p, int *ressv_p));
26 static void setabs P((struct MAINLL *start_p, int scores, short measinscore[]));
27 static void chkrestart P((struct MAINLL *start_p, struct MAINLL *end_p));
28 static void setabsscore P((struct MAINLL *start_p, struct MAINLL *end_p));
29 static void setabschord P((struct CHORD *ch_p, double nomx));
30 static double effwidth P((struct CHORD *ch_p));
31 static double bardiff P((struct MAINLL *mainll_p, struct MAINLL *end_p));
32 static void fixfullmeas P((struct CHORD *ch_p, double x));
33 static void restore_grpsyl_west P((void));
34 static void setipw P((void));
35 static void setipwgrpsyl P((struct MAINLL *mainll_p, struct GRPSYL *gs_p));
36 static void setipwchord P((struct MAINLL *mainll_p));
37 static void fixendings P((void));
38 static void fixreh P((void));
39 static void clrinhprint P((void));
40 static int hidestaffs P((struct MAINLL *mainll_p, struct MAINLL *ml2_p));
41 static int silent P((struct MAINLL *mainll_p, struct MAINLL *ml2_p, int s,
42                 int *ressv_p));
43 static 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
73 void
74 abshorz()
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
194 static void
195 barclefsigs()
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
660 static int
661 barwithssv(mainll_p)
662
663 struct 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
702 static void
703 setclefsigwid(mainll_p, chhead_p)
704
705 struct MAINLL *mainll_p;        /* point at the given clefsig's MLL struct */
706 struct 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
847 static void
848 abschunk(start_p, end_p)
849
850 struct MAINLL *start_p;         /* FEED at start of chunk of MAINLL */
851 struct MAINLL *end_p;           /* points after last struct in chunk (or 0) */
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
1020 static void
1021 tryabs(start_p, scale, scores_p, measinscore)
1022
1023 struct MAINLL *start_p;         /* FEED at start of chunk of MAINLL */
1024 double scale;                   /* inches per "whole" unit of time */
1025 int *scores_p;                  /* return number of scores needed */
1026 short measinscore[];            /* return number of measures in each score */
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
1213 static int
1214 endchunk(mainll_p)
1215
1216 struct 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
1245 static double
1246 adjust_measwid4mrpt(oldmeaswid, ch_p)
1247
1248 double oldmeaswid;      /* old measure width */
1249 struct 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
1325 static void
1326 fillclefsig(clefsig_p, feed_p)
1327
1328 struct CLEFSIG *clefsig_p;      /* points at empty clefsig to be filled in */
1329 struct MAINLL *feed_p;          /* points at a FEED in the MAINLL */
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
1446 static struct MAINLL *
1447 trymeasure(mainll_p, scale, measwidth_p, adjust_p, ressv_p)
1448
1449 struct MAINLL *mainll_p;        /* points first thing in meas, or FEED */
1450 double scale;                   /* inches per "whole" unit of time */
1451 float *measwidth_p;             /* width of measure to be filled in */
1452 float *adjust_p;                /* bar line adjust, to be filled in; if last
1453                                  * meas in score, bar shouldn't be padded on
1454                                  * right, so subtract this for measwidth */
1455 int *ressv_p;                   /* did we apply a CLEFSIG-causing SSV? */
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
1544 static void
1545 setabs(start_p, scores, measinscore)
1546
1547 struct MAINLL *start_p;         /* FEED at start of chunk of MAINLL */
1548 int scores;                     /* number of scores this chunk needs */
1549 short measinscore[];            /* number of measures in each score */
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
1625 static void
1626 chkrestart(start_p, end_p)
1627
1628 struct MAINLL *start_p;         /* point at the initial FEED of this score */
1629 struct MAINLL *end_p;           /* point after the last thing on this score */
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
1721 static void
1722 setabsscore(start_p, end_p)
1723
1724 struct MAINLL *start_p;         /* point at the initial FEED of this score */
1725 struct MAINLL *end_p;           /* point after the last thing on this score */
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
2206 static void
2207 setabschord(ch_p, nomx)
2208
2209 struct CHORD *ch_p;             /* point at the chord */
2210 double 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
2284 static double
2285 effwidth(ch_p)
2286
2287 struct 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
2331 static double
2332 bardiff(mainll_p, end_p)
2333
2334 struct MAINLL *mainll_p;        /* MLL for the bar line */
2335 struct 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
2391 static void
2392 fixfullmeas(ch_p, x)
2393
2394 struct CHORD *ch_p;             /* point at the chord */
2395 double 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
2459 static void
2460 restore_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
2531 static void
2532 setipw()
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
2649 static void
2650 setipwgrpsyl(mainll_p, gs_p)
2651
2652 struct MAINLL *mainll_p;                /* point along main linked list */
2653 struct 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
2738 static void
2739 setipwchord(mainll_p)
2740
2741 struct 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
2795 static void
2796 fixendings()
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
2910 static void
2911 fixreh()
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
2991 static void
2992 clrinhprint()
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
3074 static int
3075 hidestaffs(mainll_p, ml2_p)
3076
3077 struct MAINLL *mainll_p;        /* point at feed at start of score */
3078 struct 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
3163 static int
3164 silent(feedmll_p, ml2_p, s, ressv_p)
3165
3166 struct MAINLL *feedmll_p;       /* point along main linked list */
3167 struct MAINLL *ml2_p;           /* point at MLL item at end of this score */
3168 int s;                          /* staff number */
3169 int *ressv_p;                   /* must the caller reapply SSVs? */
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
3425 static int
3426 getmultinum(mll_p)
3427
3428 struct 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 }