| 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 | } |