| 1 | |
| 2 | /* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ |
| 3 | /* All rights reserved */ |
| 4 | |
| 5 | /* miscellaneous utility functions for music publication program, mostly |
| 6 | * for the print phase */ |
| 7 | |
| 8 | #include "defines.h" |
| 9 | #include "structs.h" |
| 10 | #include "globals.h" |
| 11 | |
| 12 | static void grp_octave_adjust P((struct GRPSYL *gs_p, int adj, struct MAINLL *mll_p)); |
| 13 | static void set_height_blockhead P((struct BLOCKHEAD *blockhead_p, int context, |
| 14 | struct MAINLL *mll_p)); |
| 15 | static double coord_staffscale P((float *coord_array)); |
| 16 | |
| 17 | \f |
| 18 | |
| 19 | /* set _cur location variable to specified value */ |
| 20 | |
| 21 | void |
| 22 | set_cur(x, y) |
| 23 | |
| 24 | float x, y; /* x, east, and west get set to x value. y, north and south, |
| 25 | * get set to y value */ |
| 26 | |
| 27 | { |
| 28 | float *cur_p; /* coord array for _cur in current context */ |
| 29 | |
| 30 | |
| 31 | /* look up _cur symbol and fill in the values */ |
| 32 | cur_p = symval("_cur", (float **) 0); |
| 33 | cur_p[AX] = cur_p[AE] = cur_p[AW] = x; |
| 34 | cur_p[AY] = cur_p[AN] = cur_p[AS] = y; |
| 35 | } |
| 36 | \f |
| 37 | |
| 38 | /* set the values for location variable _win */ |
| 39 | |
| 40 | void |
| 41 | set_win(n, s, e, w) |
| 42 | |
| 43 | float n, s, e, w; /* north, south, east, and west */ |
| 44 | |
| 45 | { |
| 46 | float *window; /* coordinate info for _win */ |
| 47 | |
| 48 | |
| 49 | /* look up symbol and fill in values */ |
| 50 | window = symval("_win", (float **) 0); |
| 51 | window[AN] = n; |
| 52 | window[AS] = s; |
| 53 | window[AE] = e; |
| 54 | window[AW] = w; |
| 55 | /* set x and y to midpoints of rectangle */ |
| 56 | window[AY] = s + (n - s)/2.0; |
| 57 | window[AX] = w + (e - w)/2.0; |
| 58 | } |
| 59 | \f |
| 60 | |
| 61 | /* Return width of a bar line. Allow a couple pixels on either side |
| 62 | * of the actual line(s) [and dots]. Does not include user padding. |
| 63 | * Since an invisbar has no lines or dots, it has zero width. |
| 64 | */ |
| 65 | |
| 66 | double |
| 67 | width_barline(bar_p) |
| 68 | |
| 69 | struct BAR *bar_p; /* return width of this bar line */ |
| 70 | |
| 71 | { |
| 72 | if (bar_p == (struct BAR *) 0) { |
| 73 | return(0.0); |
| 74 | } |
| 75 | |
| 76 | switch(bar_p->bartype) { |
| 77 | |
| 78 | case SINGLEBAR: |
| 79 | return(7 * STDPAD); |
| 80 | |
| 81 | case DOUBLEBAR: |
| 82 | return(9 * STDPAD); |
| 83 | |
| 84 | case ENDBAR: |
| 85 | return(12 * STDPAD); |
| 86 | |
| 87 | case REPEATSTART: |
| 88 | case REPEATEND: |
| 89 | return(16 * STDPAD); |
| 90 | |
| 91 | case REPEATBOTH: |
| 92 | return(19 * STDPAD); |
| 93 | |
| 94 | case RESTART: |
| 95 | return(2.0 * HALF_RESTART_WIDTH); |
| 96 | |
| 97 | case INVISBAR: |
| 98 | return(0.0); |
| 99 | |
| 100 | default: |
| 101 | pfatal("bad bar type"); |
| 102 | /*NOTREACHED*/ |
| 103 | break; |
| 104 | } |
| 105 | |
| 106 | /*NOTREACHED*/ |
| 107 | return(0.0); |
| 108 | } |
| 109 | \f |
| 110 | |
| 111 | /* Normally, we want some padding on both sides of a bar line, |
| 112 | * but at the end of a staff, we don't want right padding. |
| 113 | * This applies either if we are at the right |
| 114 | * margin or if the next bar is a restart. |
| 115 | * This function returns how much to adjust an end-of-score bar line |
| 116 | * eastward to make it at the right edge of the score. |
| 117 | */ |
| 118 | |
| 119 | double |
| 120 | eos_bar_adjust(bar_p) |
| 121 | |
| 122 | struct BAR *bar_p; /* the bar to adjust */ |
| 123 | |
| 124 | { |
| 125 | double halfbarwidth; |
| 126 | |
| 127 | halfbarwidth = width_barline(bar_p) / 2.0; |
| 128 | switch (bar_p->bartype) { |
| 129 | case DOUBLEBAR: |
| 130 | return(halfbarwidth - STDPAD - (W_NORMAL / PPI / 2.0)); |
| 131 | case SINGLEBAR: |
| 132 | return(halfbarwidth - (W_NORMAL / PPI / 2.0)); |
| 133 | case REPEATEND: |
| 134 | return(halfbarwidth - (4.0 * STDPAD) - (W_WIDE / PPI / 2.0)); |
| 135 | case ENDBAR: |
| 136 | return(halfbarwidth - (2.0 * STDPAD) - (W_WIDE / PPI / 2.0)); |
| 137 | default: |
| 138 | break; |
| 139 | } |
| 140 | return(0.0); |
| 141 | } |
| 142 | \f |
| 143 | |
| 144 | /* width of clef, keysig, timesig */ |
| 145 | |
| 146 | double |
| 147 | width_clefsig(clefsig_p) |
| 148 | |
| 149 | struct CLEFSIG *clefsig_p; /* return width of this clefsig */ |
| 150 | |
| 151 | { |
| 152 | /* we just call the routine to print a clefsig, but with |
| 153 | * flag to tell it to not really print */ |
| 154 | return(pr_clefsig((struct MAINLL *) 0, clefsig_p, NO)); |
| 155 | } |
| 156 | \f |
| 157 | |
| 158 | /* translate clef name to clef output character */ |
| 159 | |
| 160 | int |
| 161 | clefchar(clef) |
| 162 | |
| 163 | int clef; /* TREBLE, etc */ |
| 164 | |
| 165 | { |
| 166 | switch(clef) { |
| 167 | |
| 168 | case TREBLE: |
| 169 | case TREBLE_8: |
| 170 | case FRENCHVIOLIN: |
| 171 | case TREBLE_8A: |
| 172 | return(C_GCLEF); |
| 173 | |
| 174 | case BASS: |
| 175 | return(C_FCLEF); |
| 176 | |
| 177 | default: |
| 178 | /* everything else uses the C clef */ |
| 179 | return(C_CCLEF); |
| 180 | } |
| 181 | } |
| 182 | \f |
| 183 | |
| 184 | /* Returns width of the given clef in inches in the default size. |
| 185 | * If is_small is YES, give width of the 3/4 sized one used in mid-score, |
| 186 | * rather than the full-sized used at beginning of line. |
| 187 | * Caller must adjust by staffscale if they need that. |
| 188 | * No padding is included beyond the padding of the clef music character |
| 189 | * itself, so caller needs to add any they deem appropriate for aesthetics. |
| 190 | */ |
| 191 | |
| 192 | double |
| 193 | clefwidth(clef, is_small) |
| 194 | |
| 195 | int clef; /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */ |
| 196 | int is_small; /* If YES, assume mid-score clef, not full sized one */ |
| 197 | |
| 198 | { |
| 199 | return(width(FONT_MUSIC, (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE), |
| 200 | clefchar(clef))); |
| 201 | } |
| 202 | \f |
| 203 | |
| 204 | /* Returns where the given clef's baseline should be |
| 205 | * relative to the middle line of the staff, in stepsizes. |
| 206 | * (Above the middle line is positive, below is negative). |
| 207 | * If north_p and/or south_p are non-null, the relative north/south values |
| 208 | * of the clef are returned via the pointers. These will be relative |
| 209 | * to the middle line of the staff and will be in inches |
| 210 | * in the default staffscale, using default size |
| 211 | * (unless is_small == YES, in which case it will be 3/4 size). |
| 212 | * Note that this should not be called with TABCLEF or NOCLEF. |
| 213 | */ |
| 214 | |
| 215 | int |
| 216 | clefvert(clef, is_small, north_p, south_p) |
| 217 | |
| 218 | int clef; /* TREBLE, BASS, ALTO, FRENCHVIOLIN, etc */ |
| 219 | int is_small; /* If YES, assume mid-score clef, not full sized one. |
| 220 | * Note that if both of the following arguments are null, |
| 221 | * this is_small argument's value is actually irrelevent. */ |
| 222 | float *north_p; /* if non-null, relative north will be returned here */ |
| 223 | float *south_p; /* if non-null, relative south will be returned here */ |
| 224 | |
| 225 | { |
| 226 | int steps; /* relative to middle line, to be returned */ |
| 227 | |
| 228 | switch(clef) { |
| 229 | |
| 230 | case TREBLE: |
| 231 | case TREBLE_8: |
| 232 | case TREBLE_8A: |
| 233 | steps = -2; |
| 234 | break; |
| 235 | |
| 236 | case FRENCHVIOLIN: |
| 237 | case SOPRANO: |
| 238 | steps = -4; |
| 239 | break; |
| 240 | |
| 241 | case MEZZOSOPRANO: |
| 242 | steps = -2; |
| 243 | break; |
| 244 | |
| 245 | case ALTO: |
| 246 | steps = 0; |
| 247 | break; |
| 248 | |
| 249 | case TENOR: |
| 250 | steps = 2; |
| 251 | break; |
| 252 | |
| 253 | case BARITONE: |
| 254 | steps = 4; |
| 255 | break; |
| 256 | |
| 257 | case BASS: |
| 258 | steps = 2; |
| 259 | break; |
| 260 | |
| 261 | case TABCLEF: |
| 262 | default: |
| 263 | pfatal("clefvert called with invalid clef %d", clef); |
| 264 | /*NOTREACHED*/ |
| 265 | steps = 0; /* shut up bogus compiler warning */ |
| 266 | break; |
| 267 | } |
| 268 | |
| 269 | /* If caller wants relative north/south values, calculate them */ |
| 270 | if (north_p != 0 || south_p != 0) { |
| 271 | char muschar; /* music character to print for the clef */ |
| 272 | int clefsize; |
| 273 | char tr8str[4]; /* "8" of treble8 or 8treble */ |
| 274 | float value; /* of north or south */ |
| 275 | |
| 276 | muschar = clefchar(clef); |
| 277 | clefsize = (is_small ? (3 * DFLT_SIZE) / 4 : DFLT_SIZE); |
| 278 | tr8str[0] = FONT_TI; |
| 279 | tr8str[1] = 9; |
| 280 | tr8str[2] = '8'; |
| 281 | tr8str[3] = '\0'; |
| 282 | |
| 283 | if (north_p != 0) { |
| 284 | value = (float) ascent(FONT_MUSIC, clefsize, muschar); |
| 285 | if (clef == TREBLE_8A) { |
| 286 | value += (float) strheight(tr8str); |
| 287 | } |
| 288 | *north_p = value + (float)(steps * STEPSIZE); |
| 289 | } |
| 290 | |
| 291 | if (south_p != 0) { |
| 292 | value = (float) descent(FONT_MUSIC, clefsize, muschar); |
| 293 | if (clef == TREBLE_8) { |
| 294 | value += (float) strheight(tr8str); |
| 295 | } |
| 296 | *south_p = -value + (float)(steps * STEPSIZE); |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | return(steps); |
| 301 | } |
| 302 | \f |
| 303 | |
| 304 | /* Given a BLOCKHEAD, fill in its height. BLOCKHEADs are a bit strange, |
| 305 | * in that they are in a separate coordinate space of unknown size. |
| 306 | * So we start out assuming it is infinitely thin. Then we check |
| 307 | * each string in the list and keep track of the lowest one, by |
| 308 | * pretending to go where it would be printed and adding the descent |
| 309 | * of the string. At the end, the height must be the page height minus the |
| 310 | * lowest, since upwards is positive */ |
| 311 | |
| 312 | static void |
| 313 | set_height_blockhead(blockhead_p, context, mll_p) |
| 314 | |
| 315 | struct BLOCKHEAD *blockhead_p; /* which block to get height of */ |
| 316 | int context; /* C_HEADER, etc */ |
| 317 | struct MAINLL *mll_p; /* for getting margin overrides */ |
| 318 | |
| 319 | { |
| 320 | float distance; /* of headfoot from bottom of page */ |
| 321 | float lowest; |
| 322 | float x_offset; /* because of justification */ |
| 323 | float yval; /* y coordinate value */ |
| 324 | struct PRINTDATA *pr_p; /* walk through list of things to print */ |
| 325 | float block_width; /* page width minus margins */ |
| 326 | float s_descent; /* strdescent() of the current string */ |
| 327 | float extra; /* how much farther the string descended |
| 328 | * than would be expected of a normal, |
| 329 | * single line. */ |
| 330 | struct MAINLL *rightmargin_mll_p; /* mll_p to use for |
| 331 | * finding the right margin */ |
| 332 | |
| 333 | |
| 334 | /* Set _win in this context to zero height at top margin */ |
| 335 | Context = context; |
| 336 | rightmargin_mll_p = (mll_p ? mll_p->next : 0); |
| 337 | set_win_coord(blockhead_p->c); |
| 338 | set_win(PGHEIGHT - EFF_TOPMARGIN, PGHEIGHT - EFF_TOPMARGIN, |
| 339 | PGWIDTH - eff_rightmargin(rightmargin_mll_p), |
| 340 | eff_leftmargin(mll_p)); |
| 341 | block_width = PGWIDTH - eff_rightmargin(rightmargin_mll_p) - |
| 342 | eff_leftmargin(mll_p); |
| 343 | |
| 344 | if (blockhead_p->printdata_p != (struct PRINTDATA *) 0) { |
| 345 | /* set current to left corner */ |
| 346 | set_cur(eff_leftmargin((struct MAINLL *)0), |
| 347 | PGHEIGHT - EFF_TOPMARGIN); |
| 348 | |
| 349 | distance = _Cur[AY]; |
| 350 | |
| 351 | /* Process each item in the list */ |
| 352 | for (pr_p = blockhead_p->printdata_p; |
| 353 | pr_p != (struct PRINTDATA *) 0; |
| 354 | pr_p = pr_p->next) { |
| 355 | |
| 356 | /* If this is a paragraph, |
| 357 | * split it into as many lines as needed. */ |
| 358 | if (pr_p->justifytype == J_JUSTPARA || |
| 359 | pr_p->justifytype == J_RAGPARA) { |
| 360 | pr_p->string = split_string(pr_p->string, |
| 361 | block_width); |
| 362 | } |
| 363 | pr_p->width = strwidth(pr_p->string); |
| 364 | /* stretch justified paragraphs to full width */ |
| 365 | if (pr_p->justifytype == J_JUSTPARA && |
| 366 | pr_p->width < block_width) { |
| 367 | pr_p->width = block_width; |
| 368 | } |
| 369 | |
| 370 | /* adjust for justification */ |
| 371 | switch (pr_p->justifytype) { |
| 372 | |
| 373 | case J_RIGHT: |
| 374 | x_offset = pr_p->width; |
| 375 | break; |
| 376 | |
| 377 | case J_CENTER: |
| 378 | x_offset = pr_p->width / 2.0; |
| 379 | break; |
| 380 | |
| 381 | default: |
| 382 | x_offset = 0.0; |
| 383 | break; |
| 384 | } |
| 385 | |
| 386 | /* set current to specified location */ |
| 387 | yval = inpc_y (&(pr_p->location), (char *) 0, -1); |
| 388 | set_cur( inpc_x( &(pr_p->location), (char *) 0, -1 ) |
| 389 | - x_offset, yval); |
| 390 | |
| 391 | /* if user said to go off of south or y of _win, |
| 392 | * change to equivalent offset off of north of _win. |
| 393 | * because the south and y could change */ |
| 394 | if (pr_p->location.vtype == AS || |
| 395 | pr_p->location.vtype == AY) { |
| 396 | if (pr_p->location.vert_p == blockhead_p->c) { |
| 397 | pr_p->location.vtype = AN; |
| 398 | pr_p->location.vsteps = (yval |
| 399 | - (PGHEIGHT - EFF_TOPMARGIN) |
| 400 | ) / STEPSIZE; |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | /* determine lowest descent of current string */ |
| 405 | if (pr_p->isPostScript == YES) { |
| 406 | s_descent = 0.0; |
| 407 | } |
| 408 | else { |
| 409 | s_descent = strdescent(pr_p->string); |
| 410 | } |
| 411 | lowest = _Cur[AY] - s_descent; |
| 412 | |
| 413 | /* if lowest of anything found so far, note that */ |
| 414 | if ( lowest < distance) { |
| 415 | distance = lowest; |
| 416 | set_win(PGHEIGHT - EFF_TOPMARGIN, distance, |
| 417 | PGWIDTH - eff_rightmargin((struct MAINLL *)0), |
| 418 | eff_leftmargin((struct MAINLL *)0)); |
| 419 | } |
| 420 | |
| 421 | /* Set to end of string just "printed." |
| 422 | * If the string when down farther than a single line |
| 423 | * add in that extra. |
| 424 | */ |
| 425 | if (pr_p->isPostScript == YES) { |
| 426 | extra = 0.0; |
| 427 | } |
| 428 | else { |
| 429 | extra = s_descent - fontdescent(pr_p->string[0], |
| 430 | pr_p->string[1]); |
| 431 | if (extra < 0.0) { |
| 432 | extra = 0.0; |
| 433 | } |
| 434 | } |
| 435 | set_cur( _Cur[AX] + pr_p->width, _Cur[AY] - extra); |
| 436 | } |
| 437 | |
| 438 | /* set height to lowest distance encountered */ |
| 439 | blockhead_p->height = (PGHEIGHT - distance - EFF_TOPMARGIN); |
| 440 | |
| 441 | } |
| 442 | else { |
| 443 | /* empty header/footer */ |
| 444 | blockhead_p->height = 0.0; |
| 445 | } |
| 446 | |
| 447 | /* if was a footer, now we can set the actual _win coordinates, |
| 448 | * by offsetting from bottom of page instead of top */ |
| 449 | if ( (context == C_FOOTER) || (context == C_FOOT2) ) { |
| 450 | set_win(EFF_BOTMARGIN + blockhead_p->height, EFF_BOTMARGIN, |
| 451 | PGWIDTH - eff_rightmargin((struct MAINLL *)0), |
| 452 | eff_leftmargin((struct MAINLL *)0)); |
| 453 | } |
| 454 | set_win_coord(0); |
| 455 | } |
| 456 | \f |
| 457 | |
| 458 | /* Calculate the height of all blocks, including headers and footers, |
| 459 | * and fill in the height field of the struct. */ |
| 460 | |
| 461 | void |
| 462 | calc_block_heights() |
| 463 | |
| 464 | { |
| 465 | struct MAINLL *mll_p; |
| 466 | double topheight = -1.0; /* if > 0.0, is height of "top" */ |
| 467 | double botheight = -1.0; /* if > 0.0, is height of "bottom" */ |
| 468 | |
| 469 | debug(2, "calc_block_heights"); |
| 470 | |
| 471 | set_height_blockhead(&Header, C_HEADER, 0); |
| 472 | set_height_blockhead(&Footer, C_FOOTER, 0); |
| 473 | set_height_blockhead(&Header2, C_HEAD2, 0); |
| 474 | set_height_blockhead(&Footer2, C_FOOT2, 0); |
| 475 | |
| 476 | /* set main _win to space within margins and header/footer |
| 477 | * for first page. */ |
| 478 | Context = C_MUSIC; |
| 479 | |
| 480 | /* set the size of _page */ |
| 481 | _Page[AW] = _Page[AS] = 0.0; |
| 482 | _Page[AE] = PGWIDTH; |
| 483 | _Page[AN] = PGHEIGHT; |
| 484 | _Page[AX] = PGWIDTH / 2.0; |
| 485 | _Page[AY] = PGHEIGHT / 2.0; |
| 486 | |
| 487 | /* now calculate top/bot and any other blocks in the main list */ |
| 488 | initstructs(); |
| 489 | for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) { |
| 490 | if (mll_p->str == S_SSV) { |
| 491 | /* keep margins up to date */ |
| 492 | asgnssv(mll_p->u.ssv_p); |
| 493 | } |
| 494 | else if (mll_p->str == S_FEED) { |
| 495 | if (mll_p->u.feed_p->top_p != 0) { |
| 496 | set_height_blockhead(mll_p->u.feed_p->top_p, |
| 497 | C_TOP, 0); |
| 498 | if (topheight < 0.0) { |
| 499 | /* save for setting music _win */ |
| 500 | topheight = mll_p->u.feed_p->top_p->height; |
| 501 | } |
| 502 | } |
| 503 | if (mll_p->u.feed_p->top2_p != 0) { |
| 504 | set_height_blockhead(mll_p->u.feed_p->top2_p, |
| 505 | C_TOP2, 0); |
| 506 | } |
| 507 | if (mll_p->u.feed_p->bot_p != 0) { |
| 508 | set_height_blockhead(mll_p->u.feed_p->bot_p, |
| 509 | C_BOT, 0); |
| 510 | if (botheight < 0.0) { |
| 511 | /* save for setting music _win */ |
| 512 | botheight = mll_p->u.feed_p->bot_p->height; |
| 513 | } |
| 514 | } |
| 515 | if (mll_p->u.feed_p->bot2_p != 0) { |
| 516 | set_height_blockhead(mll_p->u.feed_p->bot2_p, |
| 517 | C_BOT2, 0); |
| 518 | } |
| 519 | } |
| 520 | else if (mll_p->str == S_BLOCKHEAD) { |
| 521 | set_height_blockhead(mll_p->u.blockhead_p, |
| 522 | C_BLOCK, mll_p); |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | set_win(PGHEIGHT - EFF_TOPMARGIN - Header.height |
| 527 | - (topheight > 0.0 ? topheight : 0.0), |
| 528 | EFF_BOTMARGIN + Footer.height |
| 529 | + (botheight > 0.0 ? botheight : 0.0), |
| 530 | PGWIDTH - eff_rightmargin((struct MAINLL *)0), |
| 531 | eff_leftmargin((struct MAINLL *)0)); |
| 532 | } |
| 533 | \f |
| 534 | |
| 535 | /* return number of beams or flags to use for a given basic time */ |
| 536 | |
| 537 | int |
| 538 | numbeams(btime) |
| 539 | |
| 540 | int btime; /* basic time of note to be checked */ |
| 541 | |
| 542 | { |
| 543 | int n; |
| 544 | |
| 545 | /* no beams for long notes */ |
| 546 | if (btime <= 4) { |
| 547 | return(0); |
| 548 | } |
| 549 | |
| 550 | /* number of beams is equal to the number of bits 4 has to be |
| 551 | * shifted left in order to equal the given basic time */ |
| 552 | for (n = 1; (4 << n) <= MAXBASICTIME; n++) { |
| 553 | if (btime == (4 << n)) { |
| 554 | return(n); |
| 555 | } |
| 556 | } |
| 557 | return(0); |
| 558 | } |
| 559 | \f |
| 560 | |
| 561 | /* given an accidental (#, &, x, B, n) return its music character |
| 562 | * C_SHARP, etc of the proper size. If not a valid accidental, |
| 563 | * return 0 */ |
| 564 | |
| 565 | int acc2char(acc) |
| 566 | |
| 567 | int acc; |
| 568 | |
| 569 | |
| 570 | { |
| 571 | switch (acc) { |
| 572 | |
| 573 | case '&': |
| 574 | return(C_FLAT); |
| 575 | case '#': |
| 576 | return(C_SHARP); |
| 577 | case 'n': |
| 578 | return(C_NAT); |
| 579 | case 'x': |
| 580 | return(C_DBLSHARP); |
| 581 | case 'B': |
| 582 | return(C_DBLFLAT); |
| 583 | default: |
| 584 | /* no accidental */ |
| 585 | return(0); |
| 586 | } |
| 587 | } |
| 588 | \f |
| 589 | |
| 590 | /* get the absolute x and y values for an INPCOORD */ |
| 591 | /* get the proper one of the coordinates of the specified location, and |
| 592 | * add in any offsets */ |
| 593 | |
| 594 | double |
| 595 | inpc_x(inpcoord_p, fname, lineno) |
| 596 | |
| 597 | struct INPCOORD *inpcoord_p; /* return the x value of this inpcoord */ |
| 598 | char *fname; /* filename, for error message */ |
| 599 | int lineno; /* for error message */ |
| 600 | |
| 601 | { |
| 602 | double retval; |
| 603 | |
| 604 | |
| 605 | /* if hor_p is null, then this is an absolute coord, rather |
| 606 | * than relative to some variable */ |
| 607 | if (inpcoord_p->hor_p == (float *) 0) { |
| 608 | if (inpcoord_p->counts != 0.0) { |
| 609 | /* parser should have blocked this case */ |
| 610 | pfatal("can't specify time offset if no variable specified"); |
| 611 | } |
| 612 | retval = inpcoord_p->hsteps * STEPSIZE; |
| 613 | } |
| 614 | |
| 615 | /* X location is the x, e, or w value of the specified location |
| 616 | * variable, plus any offset plus any time offset */ |
| 617 | else { |
| 618 | retval = inpcoord_p->hor_p [ inpcoord_p->htype ] |
| 619 | + inpcoord_p->hsteps * STEPSIZE |
| 620 | * coord_staffscale(inpcoord_p->hor_p) |
| 621 | + ( inpcoord_p->counts * inpcoord_p->hor_p [INCHPERWHOLE] / |
| 622 | (double) Score.timeden ); |
| 623 | } |
| 624 | |
| 625 | if (retval < 0.0 || retval > PGWIDTH) { |
| 626 | if (lineno > 0 && fname != (char *) 0) { |
| 627 | l_warning(fname, lineno, |
| 628 | "x value of %f is off the page", retval); |
| 629 | } |
| 630 | } |
| 631 | return(retval); |
| 632 | } |
| 633 | \f |
| 634 | |
| 635 | /* given an inpcoord, return its y coordinate */ |
| 636 | |
| 637 | double |
| 638 | inpc_y(inpcoord_p, fname, lineno) |
| 639 | |
| 640 | struct INPCOORD *inpcoord_p; /* return y value of this inpcoord */ |
| 641 | char *fname; /* filename, for error message */ |
| 642 | int lineno; /* for error message */ |
| 643 | |
| 644 | { |
| 645 | double retval; |
| 646 | |
| 647 | |
| 648 | /* if vert_p is null, then this is absolute rather than relative */ |
| 649 | if ( inpcoord_p->vert_p == (float *) 0) { |
| 650 | retval = inpcoord_p->vsteps * STEPSIZE; |
| 651 | } |
| 652 | |
| 653 | /* Y value is y, n, or s value of specified location variable |
| 654 | * plus any vertical offset plus any vsteps offset */ |
| 655 | else { |
| 656 | retval = inpcoord_p->vert_p [ inpcoord_p->vtype ] |
| 657 | + (inpcoord_p->vsteps * STEPSIZE |
| 658 | * coord_staffscale(inpcoord_p->vert_p)); |
| 659 | } |
| 660 | |
| 661 | if (retval < 0.0 || retval > PGHEIGHT) { |
| 662 | if (lineno > 0 && fname != (char *) 0) { |
| 663 | l_warning(fname, lineno, |
| 664 | "y value of %f is off the page", retval); |
| 665 | } |
| 666 | } |
| 667 | return(retval); |
| 668 | } |
| 669 | \f |
| 670 | |
| 671 | /* Given an INPCOORD, return the appropriate staffscale value. Look |
| 672 | * up which staff, if any, the INPCOORD is associated with, and then get |
| 673 | * the staffscale out of the SSVs. |
| 674 | */ |
| 675 | |
| 676 | static double |
| 677 | coord_staffscale(coord_array) |
| 678 | |
| 679 | float *coord_array; |
| 680 | |
| 681 | { |
| 682 | struct COORD_INFO *coord_info_p; |
| 683 | |
| 684 | |
| 685 | /* figure out what staffscale value to use, based on |
| 686 | * which staff the coordinate is associated with */ |
| 687 | if ((coord_info_p = find_coord(coord_array)) |
| 688 | != (struct COORD_INFO *) 0 && |
| 689 | coord_info_p->staffno != 0) { |
| 690 | return(svpath(coord_info_p->staffno, STAFFSCALE)->staffscale); |
| 691 | } |
| 692 | else { |
| 693 | return(1.0); |
| 694 | } |
| 695 | } |
| 696 | \f |
| 697 | |
| 698 | /* return the y coordinate of the end of a note stem */ |
| 699 | /* (the end farthest from the note head) */ |
| 700 | |
| 701 | double |
| 702 | find_y_stem(gs_p) |
| 703 | |
| 704 | struct GRPSYL *gs_p; /* which group to get the stem of */ |
| 705 | |
| 706 | { |
| 707 | /* error checks */ |
| 708 | if (gs_p == (struct GRPSYL *) 0) { |
| 709 | pfatal("null group passed to find_y_stem"); |
| 710 | } |
| 711 | |
| 712 | if (gs_p->nnotes == 0) { |
| 713 | pfatal("group with no notes passed to find_y_stem (from line %d, grpcont %d)", |
| 714 | gs_p->inputlineno, gs_p->grpcont); |
| 715 | } |
| 716 | |
| 717 | /* if stem is up, start at bottom note, if down at top */ |
| 718 | if (gs_p->stemdir == UP) { |
| 719 | return(gs_p->notelist[ gs_p->nnotes - 1].c[AY] + gs_p->stemlen); |
| 720 | } |
| 721 | else { |
| 722 | return(gs_p->notelist[0].c[AY] - gs_p->stemlen); |
| 723 | } |
| 724 | } |
| 725 | \f |
| 726 | |
| 727 | /* return x coordinate of a note stem */ |
| 728 | |
| 729 | double |
| 730 | find_x_stem(gs_p) |
| 731 | |
| 732 | struct GRPSYL *gs_p; /* return x of stem of this group */ |
| 733 | |
| 734 | { |
| 735 | double stem_adjust; /* to overlap the note head */ |
| 736 | |
| 737 | if ( gs_p == (struct GRPSYL *) 0) { |
| 738 | pfatal("bad group passed to find_x_stem"); |
| 739 | } |
| 740 | |
| 741 | /* if called with something longer than a half note, then there |
| 742 | * is no real stem. We must be being called for printing slashes, |
| 743 | * so in that case, the x of the "stem" is the x of the group */ |
| 744 | if (gs_p->basictime < 2) { |
| 745 | return(gs_p->c[AX]); |
| 746 | } |
| 747 | |
| 748 | /* move stem by half of stem width so edge lines up with edge of note */ |
| 749 | stem_adjust = W_NORMAL / PPI / 2.0; |
| 750 | if (gs_p->stemdir == UP) { |
| 751 | stem_adjust = -stem_adjust; |
| 752 | } |
| 753 | return(gs_p->c[AX] + (gs_p->stemx + stem_adjust) * Staffscale); |
| 754 | } |
| 755 | \f |
| 756 | |
| 757 | /* return the width of a key signature in inches */ |
| 758 | |
| 759 | double |
| 760 | width_keysig(sharps, naturals) |
| 761 | |
| 762 | int sharps; /* how many sharps to print, or if negative, how many flats. */ |
| 763 | int naturals; /* how many naturals to print for canceling previous key */ |
| 764 | |
| 765 | { |
| 766 | double total_width = 0.0; |
| 767 | int size; |
| 768 | |
| 769 | /* In keysig, things are drawn closer together than |
| 770 | * in other places, so to get the total width, we first |
| 771 | * multiply the width of the sharp, flat, or natural character |
| 772 | * by the number of times it is to be printed, then subtract off |
| 773 | * two points for each character printed, except for naturals, |
| 774 | * which are only jammed together by one point. */ |
| 775 | |
| 776 | size = adj_size(DFLT_SIZE, Staffscale, (char *) 0, -1); |
| 777 | if (sharps >= 1) { |
| 778 | total_width = (width(FONT_MUSIC, size, C_SHARP) - 2.0 * Stdpad) |
| 779 | * sharps; |
| 780 | } |
| 781 | else if (sharps <= -1) { |
| 782 | /* negative sharps are flats */ |
| 783 | total_width = (width(FONT_MUSIC, size, C_FLAT) - 2.0 * Stdpad) |
| 784 | * -sharps; |
| 785 | } |
| 786 | if (naturals != 0) { |
| 787 | total_width += (width(FONT_MUSIC, size, C_NAT) - Stdpad) |
| 788 | * abs(naturals) + 3.0 * Stdpad; |
| 789 | } |
| 790 | return(total_width); |
| 791 | } |
| 792 | \f |
| 793 | /* |
| 794 | * Name: nextgrpsyl() |
| 795 | * |
| 796 | * Abstract: Find next GRPSYL in this voice (same measure or not). |
| 797 | * |
| 798 | * Returns: Pointer to the GRPSYL, or 0 if none. |
| 799 | * |
| 800 | * Description: This function, given a GRPSYL and the MLL structure it hangs |
| 801 | * off of, returns the next GRPSYL in this voice, even if it's in |
| 802 | * the next measure. If it is in the next measure, *mll_p_p gets |
| 803 | * updated. But if that next measure is a second or later ending, |
| 804 | * it's not considered to be a "next" measure, so return 0. |
| 805 | */ |
| 806 | |
| 807 | struct GRPSYL * |
| 808 | nextgrpsyl(gs_p, mll_p_p) |
| 809 | |
| 810 | struct GRPSYL *gs_p; /* the given GRPSYL */ |
| 811 | struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */ |
| 812 | |
| 813 | { |
| 814 | struct MAINLL *mll_p; /* point at a MLL item */ |
| 815 | int endingloc; /* of the following barline */ |
| 816 | |
| 817 | |
| 818 | /* if not at end of measure, just return the next GRPSYL */ |
| 819 | if (gs_p->next != 0) { |
| 820 | return (gs_p->next); |
| 821 | } |
| 822 | |
| 823 | mll_p = *mll_p_p; /* save original MLL item */ |
| 824 | |
| 825 | /* |
| 826 | * We hit the end of the measure. We need to find the first group in |
| 827 | * the next measure. Find the coming bar line, then the corresponding |
| 828 | * staff in the next measure. We do this in case the number of staffs |
| 829 | * changes back and forth; we don't want to find the staff in some |
| 830 | * later measure. |
| 831 | */ |
| 832 | for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 && |
| 833 | (*mll_p_p)->str != S_BAR; *mll_p_p = (*mll_p_p)->next) { |
| 834 | ; |
| 835 | } |
| 836 | |
| 837 | /* if we hit the end of the MLL, there is no next GRPSYL */ |
| 838 | if (*mll_p_p == (struct MAINLL *) 0) { |
| 839 | return (struct GRPSYL *) 0; |
| 840 | } |
| 841 | |
| 842 | /* we found a bar; get its endingloc */ |
| 843 | endingloc = (*mll_p_p)->u.bar_p->endingloc; |
| 844 | |
| 845 | /* |
| 846 | * Search for this staff in next measure. If we find a pseudobar while |
| 847 | * doing this, save its endingloc in preference to the real bar's. |
| 848 | */ |
| 849 | for (*mll_p_p = (*mll_p_p)->next; *mll_p_p != (struct MAINLL *) 0 && |
| 850 | (*mll_p_p)->str != S_BAR && |
| 851 | ((*mll_p_p)->str != S_STAFF || |
| 852 | (*mll_p_p)->u.staff_p->staffno != gs_p->staffno); |
| 853 | *mll_p_p = (*mll_p_p)->next) { |
| 854 | |
| 855 | if ((*mll_p_p)->str == S_CLEFSIG && |
| 856 | (*mll_p_p)->u.clefsig_p->bar_p != (struct BAR *) 0) { |
| 857 | endingloc = (*mll_p_p)->u.clefsig_p->bar_p->endingloc; |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | /* if we hit the end or another bar before finding our staff, return */ |
| 862 | if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) { |
| 863 | return (struct GRPSYL *) 0; |
| 864 | } |
| 865 | |
| 866 | /* |
| 867 | * We found the appropriate staff in the next measure. But if we have |
| 868 | * crossed into a second or later ending, this bar doesn't really |
| 869 | * "follow" the previous bar, and we must return null. So if endingloc |
| 870 | * shows this is the case, we must search backwards to find out if we |
| 871 | * were already in an ending. |
| 872 | */ |
| 873 | if (endingloc == STARTITEM) { |
| 874 | while (mll_p != 0 && mll_p->str != S_BAR && (mll_p->str != |
| 875 | S_CLEFSIG || mll_p->u.clefsig_p->bar_p == 0)) |
| 876 | mll_p = mll_p->prev; |
| 877 | |
| 878 | /* set endingloc of the previous measure */ |
| 879 | if (mll_p == 0) { |
| 880 | endingloc = NOITEM; |
| 881 | } else if (mll_p->str == S_BAR) { |
| 882 | endingloc = mll_p->u.bar_p->endingloc; |
| 883 | } else { |
| 884 | endingloc = mll_p->u.clefsig_p->bar_p->endingloc; |
| 885 | } |
| 886 | |
| 887 | /* if we were already in an ending, there's no next GRPSYL */ |
| 888 | if (endingloc == STARTITEM || endingloc == INITEM) { |
| 889 | return (struct GRPSYL *) 0; |
| 890 | } |
| 891 | } |
| 892 | |
| 893 | /* return the first GRPSYL of the appropriate voice */ |
| 894 | return ((*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ]); |
| 895 | } |
| 896 | \f |
| 897 | /* |
| 898 | * Name: prevgrpsyl() |
| 899 | * |
| 900 | * Abstract: Find previous GRPSYL in this voice (same measure or not). |
| 901 | * |
| 902 | * Returns: Pointer to the GRPSYL, or 0 if none. |
| 903 | * |
| 904 | * Description: This function, given a GRPSYL and the MLL structure it hangs |
| 905 | * off of, returns the previous GRPSYL in this voice, even if it's |
| 906 | * in an earlier measure. If we are at the start of an ending, |
| 907 | * it skips over any previous ending and goes to the measure |
| 908 | * preceding the first ending. If the resulting GRPSYL is in a |
| 909 | * previous measure, *mll_p_p gets updated. |
| 910 | */ |
| 911 | |
| 912 | struct GRPSYL * |
| 913 | prevgrpsyl(gs_p, mll_p_p) |
| 914 | |
| 915 | struct GRPSYL *gs_p; /* the given GRPSYL */ |
| 916 | struct MAINLL **mll_p_p; /* main linked list structure it is hanging off of */ |
| 917 | |
| 918 | { |
| 919 | struct GRPSYL *gs2_p; /* for looping through prev measure's list */ |
| 920 | struct BAR *bar_p; /* point at a bar line */ |
| 921 | struct MAINLL *mll_p; /* point at a MLL item */ |
| 922 | int pseudo; /* was the last thing we saw a pseudobar? */ |
| 923 | int barcount; /* how many bar lines we looped backward thru*/ |
| 924 | int safmoae; /* "started at first measure of an ending" */ |
| 925 | |
| 926 | |
| 927 | /* if not at start of measure, just return the previous GRPSYL */ |
| 928 | if (gs_p->prev != (struct GRPSYL *) 0) { |
| 929 | return (gs_p->prev); |
| 930 | } |
| 931 | |
| 932 | /* |
| 933 | * We hit the start of the measure. Loop backwards through the MLL |
| 934 | * looking for the bar line at the start of the "previous" measure. |
| 935 | * If our measure is not the first measure of an ending, this is |
| 936 | * simply the bar at the start of the previous measure. Otherwise, |
| 937 | * this is the bar before the measure before the first ending. Also |
| 938 | * handle the cases where we fall off the start of the MLL. |
| 939 | */ |
| 940 | bar_p = 0; |
| 941 | mll_p = *mll_p_p; |
| 942 | pseudo = NO; |
| 943 | barcount = 0; |
| 944 | safmoae = NO; |
| 945 | do { |
| 946 | /* find preceding bar or pseudobar, if either exists */ |
| 947 | for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0 && |
| 948 | mll_p->str != S_BAR && |
| 949 | (mll_p->str != S_CLEFSIG || |
| 950 | mll_p->u.clefsig_p->bar_p == 0); |
| 951 | mll_p = mll_p->prev) { |
| 952 | ; |
| 953 | } |
| 954 | |
| 955 | /* |
| 956 | * If we hit the start of the MLL without crossing any bars, or |
| 957 | * just a pseudobar, there is no preceding GRPSYL, so return 0. |
| 958 | * (Depending on who is calling this function, the pseudobar at |
| 959 | * the start of the song may or may not exist.) Otherwise, it |
| 960 | * must be that we started in the second measure, or an ending |
| 961 | * that we skipped over started there. Point at the start of |
| 962 | * the MLL, and get out of the loop. Note that we can't still |
| 963 | * be in the process of skipping over endings: no ending can |
| 964 | * start at the first measure of the song, because there is no |
| 965 | * bar line there. |
| 966 | */ |
| 967 | if (mll_p == 0) { |
| 968 | if (barcount == 0 || (barcount == 1 && pseudo == YES)) { |
| 969 | return (struct GRPSYL *) 0; |
| 970 | } |
| 971 | mll_p = Mainllhc_p; |
| 972 | break; |
| 973 | } |
| 974 | |
| 975 | barcount++; |
| 976 | |
| 977 | /* |
| 978 | * Point bar_p at the relevant bar/pseudobar for checking the |
| 979 | * endingloc. If this is a pseudobar, it's relevant. If this |
| 980 | * is a bar, it's relevant only if it's the first thing we've |
| 981 | * seen, or the thing we saw last was not a pseudobar. That |
| 982 | * is, the endingloc of the bar at the end of a score is to be |
| 983 | * ignored, because the true endingloc has been moved to the |
| 984 | * next score's pseudobar. We need to worry about this because |
| 985 | * of the case where a second ending starts at the start of the |
| 986 | * new score (STARTITEM) and the previous score ends with |
| 987 | * ENDITEM, which should be ignored. |
| 988 | */ |
| 989 | if (mll_p->str == S_BAR) { |
| 990 | if (bar_p == 0 || pseudo == NO) { |
| 991 | bar_p = mll_p->u.bar_p; |
| 992 | } |
| 993 | if (pseudo == YES) { |
| 994 | barcount--; /* forget this bar */ |
| 995 | pseudo = NO; |
| 996 | } |
| 997 | } else { |
| 998 | bar_p = mll_p->u.clefsig_p->bar_p; |
| 999 | pseudo = YES; |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | * If this is the first measure we're backing into, and this |
| 1004 | * first bar we hit shows that our GRPSYL was in the first |
| 1005 | * measure of an ending, remember that fact. |
| 1006 | */ |
| 1007 | if (barcount == 1 && bar_p->endingloc == STARTITEM) { |
| 1008 | safmoae = YES; |
| 1009 | } |
| 1010 | |
| 1011 | /* |
| 1012 | * Get out, when, in the normal case, we've hit the second meaningful |
| 1013 | * bar; or in the safmoae case, we've skipped back to the back before |
| 1014 | * the first bar of the first ending. |
| 1015 | */ |
| 1016 | } while (! ( (safmoae == NO && barcount == 2) || (safmoae == YES && |
| 1017 | (bar_p->endingloc == NOITEM || bar_p->endingloc == ENDITEM)))); |
| 1018 | |
| 1019 | /* |
| 1020 | * Search forward to the next bar, which is the bar before which we |
| 1021 | * want to find a GRPSYL. We don't care about pseudobars here. |
| 1022 | */ |
| 1023 | for (mll_p = mll_p->next; mll_p->str != S_BAR; mll_p = mll_p->next) { |
| 1024 | ; |
| 1025 | } |
| 1026 | |
| 1027 | /* |
| 1028 | * Now mll_p is the bar before which we want to find the GRPSYL. |
| 1029 | * Find the corresponding staff in the previous measure. We do |
| 1030 | * this in case the number of staffs changes back and forth; we |
| 1031 | * don't want to find the staff in some earlier measure. |
| 1032 | */ |
| 1033 | |
| 1034 | /* search for this staff in previous measure */ |
| 1035 | for (*mll_p_p = mll_p->prev; *mll_p_p != (struct MAINLL *) 0 && |
| 1036 | (*mll_p_p)->str != S_BAR && |
| 1037 | ((*mll_p_p)->str != S_STAFF || |
| 1038 | (*mll_p_p)->u.staff_p->staffno != gs_p->staffno); |
| 1039 | *mll_p_p = (*mll_p_p)->prev) { |
| 1040 | ; |
| 1041 | } |
| 1042 | |
| 1043 | /* if we hit the start or another bar before finding our staff, return*/ |
| 1044 | if (*mll_p_p == (struct MAINLL *) 0 || (*mll_p_p)->str == S_BAR) { |
| 1045 | return (struct GRPSYL *) 0; |
| 1046 | } |
| 1047 | |
| 1048 | /* return the last GRPSYL of the appropriate voice */ |
| 1049 | gs2_p = (*mll_p_p)->u.staff_p->groups_p[ gs_p->vno - 1 ]; |
| 1050 | if (gs2_p == (struct GRPSYL *) 0) { |
| 1051 | return(gs2_p); |
| 1052 | } |
| 1053 | while (gs2_p->next != (struct GRPSYL *) 0) { |
| 1054 | gs2_p = gs2_p->next; |
| 1055 | } |
| 1056 | |
| 1057 | return (gs2_p); |
| 1058 | } |
| 1059 | \f |
| 1060 | |
| 1061 | /* if user asked for octave marks, we need to transpose any affected notes |
| 1062 | * by the appropriate number of octaves. This should be called for a measure |
| 1063 | * at a time. It will handle all the octave marks |
| 1064 | * within the measure for the current voice, both those carrying over into |
| 1065 | * this measure and ones starting there. If an octave mark spills beyond |
| 1066 | * the end of the measure, the amount to transpose and how long to do so |
| 1067 | * is saved away for use in the next measure. Checks for things becoming |
| 1068 | * out of range because of the transposition are not done here; caller |
| 1069 | * must do that if they care. */ |
| 1070 | |
| 1071 | void |
| 1072 | octave_transpose(staff_p, mll_p, vno, normdir) |
| 1073 | |
| 1074 | struct STAFF *staff_p; |
| 1075 | struct MAINLL *mll_p; /* staff_p connects here, used for bends */ |
| 1076 | int vno; /* voice number */ |
| 1077 | int normdir; /* YES if should move note pitches up for above and |
| 1078 | * down for below. NO if the inverse should be done */ |
| 1079 | |
| 1080 | { |
| 1081 | struct GRPSYL *gs_p; /* walk through list of GRPSYLs */ |
| 1082 | struct GRPSYL *gs_roll_p; /* group generated for a roll */ |
| 1083 | struct STUFF *stuff_p; /* to look for octave marks */ |
| 1084 | RATIONAL total_time; /* accumulated time in measure */ |
| 1085 | float float_total_time; /* for comparing with count */ |
| 1086 | int carry_adjust; /* adjust to carry into next measure */ |
| 1087 | int carry_bars; /* how many bars to carry over */ |
| 1088 | float carry_counts; /* how many counts in final bar */ |
| 1089 | int staffno; /* which staff we are working with */ |
| 1090 | |
| 1091 | |
| 1092 | staffno = staff_p->staffno; |
| 1093 | carry_adjust = carry_bars = 0; |
| 1094 | carry_counts = 0.0; |
| 1095 | |
| 1096 | /* if currently have octave mark */ |
| 1097 | if (Octave_adjust[staffno] != 0) { |
| 1098 | |
| 1099 | /* if bar count > 0, transpose all notes in measure */ |
| 1100 | if (--(Octave_bars[staffno]) > 0) { |
| 1101 | |
| 1102 | for (gs_p = staff_p->groups_p[vno]; |
| 1103 | gs_p != (struct GRPSYL *) 0; |
| 1104 | gs_p = gs_p->next) { |
| 1105 | |
| 1106 | grp_octave_adjust(gs_p, Octave_adjust[staffno], mll_p); |
| 1107 | } |
| 1108 | } |
| 1109 | |
| 1110 | /* otherwise just transpose until specified time */ |
| 1111 | else { |
| 1112 | total_time = Zero; |
| 1113 | for (gs_p = staff_p->groups_p[vno]; |
| 1114 | gs_p != (struct GRPSYL *) 0; |
| 1115 | gs_p = gs_p->next) { |
| 1116 | |
| 1117 | float_total_time = RAT2FLOAT(total_time) |
| 1118 | * Score.timeden + 1.0; |
| 1119 | |
| 1120 | if (float_total_time <= Octave_count[staffno]) { |
| 1121 | grp_octave_adjust(gs_p, |
| 1122 | Octave_adjust[staffno], mll_p); |
| 1123 | } |
| 1124 | else { |
| 1125 | break; |
| 1126 | } |
| 1127 | total_time = radd(total_time, gs_p->fulltime); |
| 1128 | } |
| 1129 | |
| 1130 | Octave_adjust[staffno] = 0; |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | /* go through stuff list. If any octave marks, transpose appropriate |
| 1135 | * notes in this measure. If extends to next measure, remember for |
| 1136 | * next time. If user put in more than one octave |
| 1137 | * mark going over the bar, catch that. If there are overlaps within |
| 1138 | * a measure, it seems like too much trouble to catch this, so just |
| 1139 | * transpose as often as they say and let them figure out why it |
| 1140 | * sounds funny. */ |
| 1141 | for (stuff_p = staff_p->stuff_p; stuff_p != (struct STUFF *) 0; |
| 1142 | stuff_p = stuff_p->next) { |
| 1143 | |
| 1144 | if (stuff_p->stuff_type == ST_OCTAVE) { |
| 1145 | |
| 1146 | if (Octave_adjust[staffno] != 0) { |
| 1147 | l_warning(stuff_p->inputfile, |
| 1148 | stuff_p->inputlineno, |
| 1149 | "overlapping octave marks"); |
| 1150 | } |
| 1151 | |
| 1152 | /* figure out how many octaves to move */ |
| 1153 | Octave_adjust[staffno] = parse_octave(stuff_p->string, |
| 1154 | stuff_p->place, stuff_p->inputfile, |
| 1155 | stuff_p->inputlineno); |
| 1156 | |
| 1157 | /* if this call is for inverse transpostion, adjust |
| 1158 | * to go in opposite direction */ |
| 1159 | if (normdir == NO) { |
| 1160 | Octave_adjust[staffno] *= -1; |
| 1161 | } |
| 1162 | |
| 1163 | /* figure out to which count the octave mark applies |
| 1164 | * within this measure. */ |
| 1165 | Octave_count[staffno] = (stuff_p->end.bars > 0 ? 1.0 + |
| 1166 | RAT2FLOAT(Score.time) * Score.timeden |
| 1167 | : stuff_p->end.count); |
| 1168 | |
| 1169 | total_time = Zero; |
| 1170 | for (gs_p = staff_p->groups_p[vno]; |
| 1171 | gs_p != (struct GRPSYL *) 0; |
| 1172 | gs_p = gs_p->next) { |
| 1173 | |
| 1174 | float_total_time = RAT2FLOAT(total_time) * |
| 1175 | Score.timeden + 1.0; |
| 1176 | if (float_total_time >= stuff_p->start.count) { |
| 1177 | |
| 1178 | if (float_total_time <= |
| 1179 | Octave_count[staffno]) { |
| 1180 | /* is within the mark, so move */ |
| 1181 | grp_octave_adjust(gs_p, |
| 1182 | Octave_adjust[staffno], |
| 1183 | mll_p); |
| 1184 | } |
| 1185 | |
| 1186 | /* special case. If we have a rolled |
| 1187 | * chord, and user specified |
| 1188 | * an octave mark without a til clause, |
| 1189 | * all the chords that got |
| 1190 | * generated internally to cause the |
| 1191 | * "roll" effect need to be transposed, |
| 1192 | * even though they have been moved |
| 1193 | * in time */ |
| 1194 | if (float_total_time == stuff_p->start.count |
| 1195 | && stuff_p->end.bars == 0 |
| 1196 | && stuff_p->end.count == 0.0 |
| 1197 | && gs_p->inputlineno < 0) { |
| 1198 | |
| 1199 | /* adjust all the groups generated |
| 1200 | * to create the roll effect */ |
| 1201 | for (gs_roll_p = gs_p->next; |
| 1202 | gs_roll_p != (struct GRPSYL *) 0; |
| 1203 | gs_roll_p = gs_roll_p->next) { |
| 1204 | |
| 1205 | grp_octave_adjust(gs_roll_p, |
| 1206 | Octave_adjust[staffno], |
| 1207 | mll_p); |
| 1208 | /* stop when we hit the |
| 1209 | * end of the roll */ |
| 1210 | if (gs_roll_p->inputlineno > 0) { |
| 1211 | break; |
| 1212 | } |
| 1213 | } |
| 1214 | } |
| 1215 | } |
| 1216 | |
| 1217 | total_time = radd(total_time, gs_p->fulltime); |
| 1218 | } |
| 1219 | |
| 1220 | /* if octave mark carried over into subsequent |
| 1221 | * measure(s), make a note of that for future use */ |
| 1222 | if (stuff_p->end.bars > 0) { |
| 1223 | if (carry_adjust != 0) { |
| 1224 | l_warning(stuff_p->inputfile, |
| 1225 | stuff_p->inputlineno, |
| 1226 | "overlapping octave marks"); |
| 1227 | } |
| 1228 | carry_bars = stuff_p->end.bars; |
| 1229 | carry_counts = stuff_p->end.count; |
| 1230 | carry_adjust = Octave_adjust[staffno]; |
| 1231 | } |
| 1232 | |
| 1233 | Octave_adjust[staffno] = 0; |
| 1234 | } |
| 1235 | } |
| 1236 | |
| 1237 | /* above octave marks that were put in on the same input line will |
| 1238 | * be in backwards order (because above stuff needs to be that |
| 1239 | * way to pile on correctly). However, if the last octave in the |
| 1240 | * stuff input line carried over a bar line, we would see it |
| 1241 | * first and lose the carryover information when handling the earlier |
| 1242 | * octave marks (which are later in the stuff list). That's why the |
| 1243 | * carryover information had to be saved. Now we can assign it */ |
| 1244 | if (carry_bars > 0) { |
| 1245 | Octave_adjust[staffno] = carry_adjust; |
| 1246 | Octave_bars[staffno] = carry_bars; |
| 1247 | Octave_count[staffno] = carry_counts; |
| 1248 | } |
| 1249 | } |
| 1250 | \f |
| 1251 | |
| 1252 | /* transpose all the notes in a group by the specified octave adjustment */ |
| 1253 | |
| 1254 | static void |
| 1255 | grp_octave_adjust(gs_p, adj, mll_p) |
| 1256 | |
| 1257 | struct GRPSYL *gs_p; /* adjust this group */ |
| 1258 | int adj; /* add this (potentially negative) value to |
| 1259 | * each notelist octave */ |
| 1260 | struct MAINLL *mll_p; /* STAFF of gs_p for finding prev grp for bends */ |
| 1261 | |
| 1262 | { |
| 1263 | register int n; |
| 1264 | struct GRPSYL *prevgs_p; /* previous group, for bends */ |
| 1265 | |
| 1266 | for (n = 0; n < gs_p->nnotes; n++) { |
| 1267 | gs_p->notelist[n].octave += adj; |
| 1268 | } |
| 1269 | /* Transpose any bends going to this group */ |
| 1270 | prevgs_p = prevgrpsyl(gs_p, &mll_p); |
| 1271 | if (prevgs_p == 0) { |
| 1272 | /* If there is no previous group, nothing to transpose. */ |
| 1273 | return; |
| 1274 | } |
| 1275 | for (n = 0; n < prevgs_p->nnotes; n++) { |
| 1276 | if (prevgs_p->notelist[n].is_bend == YES) { |
| 1277 | /* Note that when is_bend is YES, nslurto will always |
| 1278 | * be 1, but we loop through as many as there are |
| 1279 | * (all 1 of them!), to not be dependent |
| 1280 | * on that piece of inside information. |
| 1281 | */ |
| 1282 | int s; |
| 1283 | for (s = 0; s < prevgs_p->notelist[n].nslurto; s++) { |
| 1284 | prevgs_p->notelist[n].slurtolist[s].octave += adj; |
| 1285 | } |
| 1286 | } |
| 1287 | } |
| 1288 | } |
| 1289 | \f |
| 1290 | |
| 1291 | /* Given a group and note value, return the effective accidental |
| 1292 | * on that note, (-2 to +2) taking key signature |
| 1293 | * and previous accidentals into account. |
| 1294 | * There are certain pathological cases that this doesn't |
| 1295 | * handle right, notably if the user changes the key signature at a bar |
| 1296 | * line, and the note in question is tied to from before that bar line, |
| 1297 | * and the key signature change is such that it changes what the accidental |
| 1298 | * should be. But it should handle anything less convoluted than that. |
| 1299 | */ |
| 1300 | |
| 1301 | int |
| 1302 | eff_acc(gs_p, note_p, mll_p) |
| 1303 | |
| 1304 | struct GRPSYL *gs_p; /* get effective accidental for note in this group */ |
| 1305 | struct NOTE *note_p; /* get for this note */ |
| 1306 | struct MAINLL *mll_p; /* main list item that points to gs_p */ |
| 1307 | |
| 1308 | { |
| 1309 | struct MAINLL *orig_mll_p; |
| 1310 | struct GRPSYL *pgs_p; /* previous group */ |
| 1311 | int n; |
| 1312 | int tie_break; /* YES if there has been a break |
| 1313 | * in the chain of notes |
| 1314 | * tied together */ |
| 1315 | int eff_accidental; /* effective accidental so far */ |
| 1316 | |
| 1317 | |
| 1318 | /* if this group has an explicit accidental, that's also the |
| 1319 | * effective accidental */ |
| 1320 | if (note_p->accidental != '\0') { |
| 1321 | /* note: the - 2 is to adjust for natural being element 2 |
| 1322 | * of the Circle array */ |
| 1323 | return( (int) (strchr(Acclets, note_p->accidental) - Acclets) - 2); |
| 1324 | } |
| 1325 | |
| 1326 | /* remember which measure we are starting in, so we know when we cross |
| 1327 | * a bar line */ |
| 1328 | orig_mll_p = mll_p; |
| 1329 | |
| 1330 | /* init to assume we might have ties */ |
| 1331 | tie_break = NO; |
| 1332 | |
| 1333 | /* if all else fails, we will use the accidental from the key sig */ |
| 1334 | eff_accidental = acc_from_keysig(note_p->letter, gs_p->staffno, |
| 1335 | mll_p); |
| 1336 | |
| 1337 | /* back up until we figure out the effective accidental */ |
| 1338 | for (pgs_p = prevgrpsyl(gs_p, &mll_p); pgs_p != (struct GRPSYL *) 0; |
| 1339 | pgs_p = prevgrpsyl(pgs_p, &mll_p)) { |
| 1340 | |
| 1341 | |
| 1342 | /* see if this group contains the note in question */ |
| 1343 | for (n = 0; n < pgs_p->nnotes; n++) { |
| 1344 | if (pgs_p->notelist[n].letter == note_p->letter && |
| 1345 | pgs_p->notelist[n].octave |
| 1346 | == note_p->octave) { |
| 1347 | /* it does have the note: it's notelist[n] */ |
| 1348 | break; |
| 1349 | } |
| 1350 | } |
| 1351 | |
| 1352 | /* see if this is end of ties to the note, working backwards */ |
| 1353 | if (n == pgs_p->nnotes) { |
| 1354 | /* no note at all, so clearly no tied note */ |
| 1355 | tie_break = YES; |
| 1356 | } |
| 1357 | else if (pgs_p->notelist[n].tie == NO) { |
| 1358 | /* end of chain of tied notes */ |
| 1359 | tie_break = YES; |
| 1360 | } |
| 1361 | |
| 1362 | if (orig_mll_p == mll_p) { |
| 1363 | /* we're still in same measure. If we have a matching |
| 1364 | * note, see if it has an accidental */ |
| 1365 | if (n < pgs_p->nnotes) { |
| 1366 | if (pgs_p->notelist[n].accidental != '\0') { |
| 1367 | return( (int) (strchr(Acclets, |
| 1368 | pgs_p->notelist[n].accidental) |
| 1369 | - Acclets) - 2); |
| 1370 | } |
| 1371 | } |
| 1372 | |
| 1373 | /* have to keep backing up */ |
| 1374 | } |
| 1375 | else { |
| 1376 | /* Now in previous measure. If no matching note, |
| 1377 | * we use the effective accidental found so far */ |
| 1378 | if (n == pgs_p->nnotes) { |
| 1379 | return(eff_accidental); |
| 1380 | } |
| 1381 | |
| 1382 | /* if the note isn't tied, then use the most recent |
| 1383 | * effective accidental we found */ |
| 1384 | if (pgs_p->notelist[n].tie == NO || tie_break == YES) { |
| 1385 | return(eff_accidental); |
| 1386 | } |
| 1387 | |
| 1388 | /* if there is an accidental on this note, |
| 1389 | * then it's the one we're looking for. */ |
| 1390 | if (pgs_p->notelist[n].accidental != '\0') { |
| 1391 | return( (int) (strchr(Acclets, |
| 1392 | pgs_p->notelist[n].accidental) - |
| 1393 | Acclets - 2)); |
| 1394 | } |
| 1395 | |
| 1396 | /* need to continue working backwards toward |
| 1397 | * the beginning of this new measure */ |
| 1398 | orig_mll_p = mll_p; |
| 1399 | eff_accidental = acc_from_keysig(note_p->letter, |
| 1400 | gs_p->staffno, mll_p); |
| 1401 | } |
| 1402 | } |
| 1403 | |
| 1404 | /* backed up all the way to the beginning of the song, use last we |
| 1405 | * found */ |
| 1406 | return(eff_accidental); |
| 1407 | } |
| 1408 | \f |
| 1409 | |
| 1410 | /* given a letter and staff number, return 1 if the pitch with that letter |
| 1411 | * gets a sharps according to the key signature, or -1 if it gets a flat, |
| 1412 | * or 0 if it gets neither. */ |
| 1413 | |
| 1414 | int |
| 1415 | acc_from_keysig(letter, staffno, mll_p) |
| 1416 | |
| 1417 | int letter; /* which pitch */ |
| 1418 | int staffno; /* which staff to get the key signature from */ |
| 1419 | struct MAINLL *mll_p; /* pitch is from the staff hanging off of here */ |
| 1420 | |
| 1421 | { |
| 1422 | int index; /* where the letter is in circle of fifths */ |
| 1423 | int sharps; /* sharps in key sig for the given staff */ |
| 1424 | struct SSV *ssv_p; /* to get key signature */ |
| 1425 | |
| 1426 | |
| 1427 | /* find letter in circle of fifths */ |
| 1428 | index = strchr(Circle, letter) - Circle + 1; |
| 1429 | |
| 1430 | /* get key signature. Unfortunately, the SSVs may not be |
| 1431 | * accurate at the time we are called, so we have to search |
| 1432 | * backwards in the main list for the most recent relevant |
| 1433 | * key signature change. */ |
| 1434 | for (sharps = 0; mll_p != (struct MAINLL *) 0; mll_p = mll_p->prev) { |
| 1435 | if (mll_p->str == S_SSV) { |
| 1436 | ssv_p = mll_p->u.ssv_p; |
| 1437 | |
| 1438 | /* does this SSV have a key signature change in it? */ |
| 1439 | if (ssv_p->used[SHARPS] == YES) { |
| 1440 | if (ssv_p->context == C_STAFF && |
| 1441 | ssv_p->staffno == staffno) { |
| 1442 | /* aha! found the most recent |
| 1443 | * key signature |
| 1444 | * for the relevant staff */ |
| 1445 | sharps = ssv_p->sharps; |
| 1446 | break; |
| 1447 | } |
| 1448 | else if (ssv_p->context == C_SCORE) { |
| 1449 | /* this will be the score-wide default |
| 1450 | * if we don't find a staff-specific |
| 1451 | * value, so save this as our default */ |
| 1452 | sharps = ssv_p->sharps; |
| 1453 | } |
| 1454 | } |
| 1455 | } |
| 1456 | } |
| 1457 | |
| 1458 | if (sharps > 0) { |
| 1459 | /* key signature is one with sharps */ |
| 1460 | if (index <= sharps) { |
| 1461 | /* this letter gets a sharp */ |
| 1462 | return(1); |
| 1463 | } |
| 1464 | } |
| 1465 | else if (sharps < 0) { |
| 1466 | /* key signature is one with flats */ |
| 1467 | if ( (8 - index) <= -sharps) { |
| 1468 | /* this letter gets a flat */ |
| 1469 | return(-1); |
| 1470 | } |
| 1471 | } |
| 1472 | |
| 1473 | /* must be a natural */ |
| 1474 | return(0); |
| 1475 | } |
| 1476 | |
| 1477 | /* Set Staffscale, Stepsize, Stdpad, and other similar values based on the |
| 1478 | * specified staff number. If staff of 0 is given, set Staffscale to the |
| 1479 | * score value |
| 1480 | */ |
| 1481 | |
| 1482 | void |
| 1483 | set_staffscale(s) |
| 1484 | |
| 1485 | int s; /* which staff */ |
| 1486 | |
| 1487 | { |
| 1488 | Staffscale = (s == 0 ? Score.staffscale |
| 1489 | : svpath(s, STAFFSCALE)->staffscale); |
| 1490 | Stepsize = STEPSIZE * Staffscale; |
| 1491 | Stdpad = STDPAD * Staffscale; |
| 1492 | Flagsep = FLAGSEP * Staffscale; |
| 1493 | Smflagsep = SMFLAGSEP * Staffscale; |
| 1494 | Tupheight = TUPHEIGHT * Staffscale; |
| 1495 | } |
| 1496 | \f |
| 1497 | |
| 1498 | /* Determine the space between lines of a grid. A staff of 0 means use |
| 1499 | * the score size. A staff of -1 means ATEND. Return distance in inches. */ |
| 1500 | |
| 1501 | double |
| 1502 | gridspace(staff) |
| 1503 | |
| 1504 | int staff; |
| 1505 | |
| 1506 | { |
| 1507 | double space; |
| 1508 | |
| 1509 | if (staff == -1) { |
| 1510 | space = ATEND_GS * STEPSIZE * Score.gridscale; |
| 1511 | } |
| 1512 | else { |
| 1513 | space = WHEREUSED_GS * STEPSIZE |
| 1514 | * svpath(staff, STAFFSCALE)->staffscale |
| 1515 | * svpath(staff, GRIDSCALE)->gridscale; |
| 1516 | } |
| 1517 | return(space); |
| 1518 | } |
| 1519 | \f |
| 1520 | |
| 1521 | /* Given a grid, return (via pointer) the items needed for the PostScript |
| 1522 | * plus the top fret. |
| 1523 | */ |
| 1524 | |
| 1525 | void |
| 1526 | gridinfo(grid_p, staff, frets_p, fretnum_p, numvert_p, topfret_p) |
| 1527 | |
| 1528 | struct GRID *grid_p; |
| 1529 | int staff; /* 0 == score, -1 = ATEND, otherwise the staff number */ |
| 1530 | int *frets_p; /* how many frets high the grid should be */ |
| 1531 | int *fretnum_p; /* the N of "N fr" */ |
| 1532 | int *numvert_p; /* how many frets from the top to print the "N fr" */ |
| 1533 | int *topfret_p; /* the fret number of the top line of the grid */ |
| 1534 | |
| 1535 | { |
| 1536 | int minfret, maxfret; /* smallest and largest frets used */ |
| 1537 | int rightmost_fret; /* the 'N' of 'N fr" if any */ |
| 1538 | int right_stringnum; /* string number having rightmost_fret */ |
| 1539 | int mincurvefret; /* smallest fret number inside curve */ |
| 1540 | int has_o; /* if there are 'o' items */ |
| 1541 | int gridfret; |
| 1542 | int s; |
| 1543 | |
| 1544 | |
| 1545 | /* Go through strings finding min/max/rightmost */ |
| 1546 | minfret = MAXFRET + 1; |
| 1547 | maxfret = MINFRET - 1; |
| 1548 | mincurvefret = MAXFRET + 1; |
| 1549 | has_o = NO; |
| 1550 | rightmost_fret = right_stringnum = 0; /* avoids bogus warnings */ |
| 1551 | for (s = 0; s < grid_p->numstr; s++) { |
| 1552 | /* x o and - things don't count */ |
| 1553 | if (grid_p->positions[s] > 0) { |
| 1554 | if (grid_p->positions[s] < minfret) { |
| 1555 | minfret = grid_p->positions[s]; |
| 1556 | } |
| 1557 | if (grid_p->positions[s] > maxfret) { |
| 1558 | maxfret = grid_p->positions[s]; |
| 1559 | } |
| 1560 | rightmost_fret = grid_p->positions[s]; |
| 1561 | right_stringnum = s; |
| 1562 | |
| 1563 | /* find smallest fret inside curve */ |
| 1564 | if (grid_p->curvel != 0 && s >= grid_p->curvel - 1 && |
| 1565 | s <= grid_p->curver - 1 && |
| 1566 | grid_p->positions[s] < mincurvefret) { |
| 1567 | mincurvefret = grid_p->positions[s]; |
| 1568 | } |
| 1569 | } |
| 1570 | else if (grid_p->positions[s] == 0) { |
| 1571 | has_o = YES; |
| 1572 | } |
| 1573 | } |
| 1574 | |
| 1575 | /* set the values to defaults, then calculate actuals if needed */ |
| 1576 | *frets_p = 5; |
| 1577 | *fretnum_p = 0; |
| 1578 | *numvert_p = 0; |
| 1579 | if (minfret <= MAXFRET) { |
| 1580 | /* at least one fret was used */ |
| 1581 | |
| 1582 | /* figure out how many frets tall to make the grid */ |
| 1583 | *frets_p = maxfret + 1; |
| 1584 | |
| 1585 | /* see if gridfret is set */ |
| 1586 | gridfret = svpath(staff == -1 ? 0 : staff, GRIDFRET)->gridfret; |
| 1587 | if (gridfret != NOGRIDFRET) { |
| 1588 | /* gridfret is set; see if all frets larger than that. |
| 1589 | * But we only use "N fr" if there are no 'o' items. */ |
| 1590 | if (has_o == NO && minfret >= gridfret) { |
| 1591 | /* We will need "N fr" |
| 1592 | * Usually we use the rightmost string |
| 1593 | * that has a fret on it, |
| 1594 | * but there is one special case: |
| 1595 | * if the curve comes at least that far right, |
| 1596 | * and the minimum fret inside the curve is |
| 1597 | * smaller than the rightmost_fret, then we |
| 1598 | * put the "N fr" by the curve minimum. |
| 1599 | */ |
| 1600 | if (grid_p->curver - 1 >= right_stringnum |
| 1601 | && mincurvefret < rightmost_fret) { |
| 1602 | rightmost_fret = mincurvefret; |
| 1603 | } |
| 1604 | *fretnum_p = rightmost_fret; |
| 1605 | *numvert_p = rightmost_fret - minfret + 1; |
| 1606 | *frets_p = maxfret - minfret + 2; |
| 1607 | } |
| 1608 | } |
| 1609 | |
| 1610 | if (*frets_p < 5) { |
| 1611 | /* always at least 4 frets plus top line */ |
| 1612 | *frets_p = 5; |
| 1613 | } |
| 1614 | } |
| 1615 | *topfret_p = (*fretnum_p == 0 ? 0 : *fretnum_p - *numvert_p); |
| 1616 | } |
| 1617 | \f |
| 1618 | |
| 1619 | /* Determine the dimensions of a grid, relative to a point in the middle |
| 1620 | * of the top line of the grid, and return them via pointers. |
| 1621 | * If pointers are 0, don't bother; caller doesn't care about these things. |
| 1622 | * Things in this function must be kept in sync with the PostScript prolog |
| 1623 | * definition of grids. |
| 1624 | */ |
| 1625 | |
| 1626 | void |
| 1627 | gridsize(grid_p, staff, north_p, south_p, east_p, west_p) |
| 1628 | |
| 1629 | struct GRID *grid_p; /* find the size of this grid */ |
| 1630 | int staff; /* use this staff for scaling. 0 means score, |
| 1631 | * -1 means ATEND */ |
| 1632 | float *north_p; /* return values... */ |
| 1633 | float *south_p; |
| 1634 | float *east_p; |
| 1635 | float *west_p; |
| 1636 | |
| 1637 | { |
| 1638 | double space; /* distance between adjacent line of the grid */ |
| 1639 | int frets; |
| 1640 | int fretnum; |
| 1641 | int numvert; |
| 1642 | int topfret; |
| 1643 | int s; /* string index */ |
| 1644 | |
| 1645 | if (grid_p == 0) { |
| 1646 | pfatal("gridsize() was passed a null pointer"); |
| 1647 | } |
| 1648 | |
| 1649 | /* determine distance between grid lines and other needed info */ |
| 1650 | space = gridspace(staff); |
| 1651 | gridinfo(grid_p, staff, &frets, &fretnum, &numvert, &topfret); |
| 1652 | |
| 1653 | /* Start with minimum. East and west are equal, at half the |
| 1654 | * total grid width, based on number of strings. The number of |
| 1655 | * spaces is the number of strings minus one, but dots, X's, |
| 1656 | * and O's will hang over the sides, so use the number of strings. |
| 1657 | * Then adjust east for "N fr" if needed. */ |
| 1658 | if (west_p != 0) { |
| 1659 | *west_p = -((space * grid_p->numstr) / 2.0); |
| 1660 | } |
| 1661 | if (east_p != 0) { |
| 1662 | *east_p = (space * grid_p->numstr) / 2.0; |
| 1663 | if (fretnum > 0) { |
| 1664 | /* We will need "N fr". |
| 1665 | * Get enough space to hold |
| 1666 | * font, size, 2 digits, space, "fr", null */ |
| 1667 | char tmp[8]; |
| 1668 | |
| 1669 | /* this is printed in Palatino Roman */ |
| 1670 | tmp[0] = (char) FONT_PR; |
| 1671 | |
| 1672 | /* Between staffscale and gridscale, |
| 1673 | * we could get a size that we can't represent |
| 1674 | * in internal format, so get string width |
| 1675 | * in default size and adjust afterwards. */ |
| 1676 | tmp[1] = (char) DFLT_SIZE; |
| 1677 | |
| 1678 | /* since we know there are no funny characters |
| 1679 | * in this string, we can cheat and not bother |
| 1680 | * to call the string normalizer. */ |
| 1681 | sprintf(tmp + 2, "%d fr", fretnum); |
| 1682 | |
| 1683 | *east_p += strwidth(tmp) * |
| 1684 | (space * PPI * 1.9)/ DFLT_SIZE; |
| 1685 | } |
| 1686 | } |
| 1687 | |
| 1688 | if (north_p != 0) { |
| 1689 | /* Always put almost one space of padding on top, which allows |
| 1690 | * room for x's and o's and curves. Even if this particular grid |
| 1691 | * doesn't have those, many do, so it's nice to line |
| 1692 | * all of them up as much as possible */ |
| 1693 | *north_p = 0.85 * space; |
| 1694 | /* If there is a curve above the top fret, |
| 1695 | * with x's or o's above it, leave some more space */ |
| 1696 | if (grid_p->positions[grid_p->curvel - 1] == topfret + 1 |
| 1697 | || grid_p->positions[grid_p->curver - 1] |
| 1698 | == topfret + 1) { |
| 1699 | for (s = grid_p->curvel; s <= grid_p->curver; s++) { |
| 1700 | if (grid_p->positions[s-1] == 0 || |
| 1701 | grid_p->positions[s-1] |
| 1702 | == -1) { |
| 1703 | *north_p += 0.7 * space; |
| 1704 | break; |
| 1705 | } |
| 1706 | } |
| 1707 | } |
| 1708 | } |
| 1709 | |
| 1710 | /* Grid is always at least 4 boxes high, more if needed, |
| 1711 | * plus 1/2 space of padding at bottom */ |
| 1712 | if (south_p != 0) { |
| 1713 | *south_p = -(frets - 0.5) * space; |
| 1714 | } |
| 1715 | } |
| 1716 | \f |
| 1717 | |
| 1718 | /* This function returns the minimum distance needed between the current |
| 1719 | * staff and previous one, given their clefs and allowing for a measure |
| 1720 | * number. The clefs might be NOCLEF, like if this is for the top |
| 1721 | * staff of a page or a staff where printclef is false. |
| 1722 | */ |
| 1723 | |
| 1724 | double |
| 1725 | clefspace(prevclef, prevscale, curclef, curscale, measnum) |
| 1726 | |
| 1727 | int prevclef; /* clef on staff above */ |
| 1728 | double prevscale; /* staffscale for the staff above */ |
| 1729 | int curclef; /* clef on staff below */ |
| 1730 | double curscale; /* staffscale for the staff below */ |
| 1731 | int measnum; /* YES if a measure number needs to be printed */ |
| 1732 | |
| 1733 | { |
| 1734 | double cur_extend; /* space needed for current clef */ |
| 1735 | double prev_extend; /* space needed for clef above */ |
| 1736 | double space_needed; /* total for both clefs and measure number */ |
| 1737 | |
| 1738 | |
| 1739 | /* Figure out how much the clef on current staff sticks up, |
| 1740 | * Do in approximate STEPSIZEs here, and adjust later for scale. */ |
| 1741 | switch (curclef) { |
| 1742 | case TREBLE_8A: |
| 1743 | cur_extend = 6.0; |
| 1744 | break; |
| 1745 | case TREBLE: |
| 1746 | case TREBLE_8: |
| 1747 | cur_extend = 4.0; |
| 1748 | break; |
| 1749 | case BARITONE: |
| 1750 | cur_extend = 4.2; |
| 1751 | break; |
| 1752 | case TENOR: |
| 1753 | cur_extend = 2.2; |
| 1754 | break; |
| 1755 | case FRENCHVIOLIN: |
| 1756 | cur_extend = 2.0; |
| 1757 | break; |
| 1758 | default: |
| 1759 | cur_extend = 0.0; |
| 1760 | break; |
| 1761 | } |
| 1762 | |
| 1763 | /* Similar for the clef above, only how much it sticks down |
| 1764 | * rather than up */ |
| 1765 | switch (prevclef) { |
| 1766 | case TREBLE: |
| 1767 | case TREBLE_8A: |
| 1768 | prev_extend = 3.2; |
| 1769 | break; |
| 1770 | case MEZZOSOPRANO: |
| 1771 | prev_extend = 2.2; |
| 1772 | break; |
| 1773 | case SOPRANO: |
| 1774 | prev_extend = 4.2; |
| 1775 | break; |
| 1776 | case FRENCHVIOLIN: |
| 1777 | case TREBLE_8: |
| 1778 | prev_extend = 5.2; |
| 1779 | break; |
| 1780 | default: |
| 1781 | prev_extend = 0.0; |
| 1782 | break; |
| 1783 | } |
| 1784 | |
| 1785 | /* Add top and bottom together, adjusting for scale factors, |
| 1786 | * and adding a little padding */ |
| 1787 | space_needed = prev_extend * STEPSIZE * prevscale + |
| 1788 | cur_extend * STEPSIZE * curscale + |
| 1789 | STDPAD * curscale; |
| 1790 | |
| 1791 | /* Add on the space for the measure number, if necessary. |
| 1792 | * Note that we can use fontascent since all digits are that high. */ |
| 1793 | if (measnum == YES) { |
| 1794 | space_needed += fontascent(Score.measnumfamily + Score.measnumfont, |
| 1795 | Score.measnumsize) + STDPAD; |
| 1796 | } |
| 1797 | return(space_needed); |
| 1798 | } |
| 1799 | \f |
| 1800 | /* |
| 1801 | * Name: eff_rightmargin() |
| 1802 | * |
| 1803 | * Abstract: Return the effective right margin for this score. |
| 1804 | * |
| 1805 | * Returns: the margin in inches |
| 1806 | * |
| 1807 | * Description: There are two reason that code can't just use Score.rightmargin |
| 1808 | * but must call this function. First, the way the "scale" param |
| 1809 | * works, we pretend the paper is smaller by that amount and then |
| 1810 | * in PostScript magnify it back to the real size; but margins are |
| 1811 | * not to be scaled, so we have to fake out the code by dividing |
| 1812 | * out the scale here. Second, the user can override the param |
| 1813 | * on a "newscore" or "newpage". To ignore a user override, pass |
| 1814 | * 0 for mainll_p, else pass some MLL on that score. |
| 1815 | */ |
| 1816 | |
| 1817 | double |
| 1818 | eff_rightmargin(mainll_p) |
| 1819 | |
| 1820 | struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */ |
| 1821 | |
| 1822 | { |
| 1823 | /* if not already at a FEED, find FEED at right end of this score */ |
| 1824 | while (mainll_p != 0 && mainll_p->str != S_FEED) |
| 1825 | mainll_p = mainll_p->next; |
| 1826 | |
| 1827 | /* if there is none, or there is no override, use the parameter */ |
| 1828 | if (mainll_p == 0 || mainll_p->u.feed_p->rightmargin < 0.0) |
| 1829 | return (Score.rightmargin / Score.scale_factor); |
| 1830 | |
| 1831 | /* use this override value */ |
| 1832 | return (mainll_p->u.feed_p->rightmargin / Score.scale_factor); |
| 1833 | } |
| 1834 | \f |
| 1835 | /* |
| 1836 | * Name: eff_leftmargin() |
| 1837 | * |
| 1838 | * Abstract: Return the effective left margin for this score. |
| 1839 | * |
| 1840 | * Returns: the margin in inches |
| 1841 | * |
| 1842 | * Description: There are two reason that code can't just use Score.leftmargin |
| 1843 | * but must call this function. First, the way the "scale" param |
| 1844 | * works, we pretend the paper is smaller by that amount and then |
| 1845 | * in PostScript magnify it back to the real size; but margins are |
| 1846 | * not to be scaled, so we have to fake out the code by dividing |
| 1847 | * out the scale here. Second, the user can override the param |
| 1848 | * on a "newscore" or "newpage". To ignore a user override, pass |
| 1849 | * 0 for mainll_p, else pass some MLL on that score. |
| 1850 | */ |
| 1851 | |
| 1852 | double |
| 1853 | eff_leftmargin(mainll_p) |
| 1854 | |
| 1855 | struct MAINLL *mainll_p; /* MLL struct on some score, or 0 for normal margin */ |
| 1856 | |
| 1857 | { |
| 1858 | /* if not already at a FEED, find FEED at left end of this score */ |
| 1859 | while (mainll_p != 0 && mainll_p->str != S_FEED) |
| 1860 | mainll_p = mainll_p->prev; |
| 1861 | |
| 1862 | /* if there is none, or there is no override, use the parameter */ |
| 1863 | if (mainll_p == 0 || mainll_p->u.feed_p->leftmargin < 0.0) |
| 1864 | return (Score.leftmargin / Score.scale_factor); |
| 1865 | |
| 1866 | /* use this override value */ |
| 1867 | return (mainll_p->u.feed_p->leftmargin / Score.scale_factor); |
| 1868 | } |
| 1869 | \f |
| 1870 | /* |
| 1871 | * Name: findprimes() |
| 1872 | * |
| 1873 | * Abstract: Find all the prime numbers up to the given number ("max"). |
| 1874 | * |
| 1875 | * Returns: array indexed 0 to max, each element YES or NO (is index prime?) |
| 1876 | * |
| 1877 | * Description: This function mallocs and returns an array of shorts, indexed |
| 1878 | * from 0 to max. Each element is YES or NO, telling whether its |
| 1879 | * index is a prime number. The first time it is called, or if |
| 1880 | * max is greater than the previous time, it calculates all this, |
| 1881 | * but on other calls it just returns the answer from before. |
| 1882 | */ |
| 1883 | |
| 1884 | short * |
| 1885 | findprimes(max) |
| 1886 | |
| 1887 | int max; /* max integer we need to consider */ |
| 1888 | |
| 1889 | { |
| 1890 | static short *isprime = 0; /* array to be malloc'ed */ |
| 1891 | static int oldmax = 0; /* the max passed in previously */ |
| 1892 | int stop; /* where to stop looking */ |
| 1893 | int prime; /* a prime number */ |
| 1894 | int n; /* loop index */ |
| 1895 | |
| 1896 | |
| 1897 | /* if we've already been here ... */ |
| 1898 | if (isprime != 0) { |
| 1899 | /* if we've already done the same or more, just return answer*/ |
| 1900 | if (max <= oldmax) { |
| 1901 | return (isprime); |
| 1902 | } |
| 1903 | /* max increased; free the old array */ |
| 1904 | FREE(isprime); |
| 1905 | } |
| 1906 | oldmax = max; /* remember if for next time */ |
| 1907 | |
| 1908 | MALLOCA(short, isprime, max + 1); |
| 1909 | |
| 1910 | /* 0 and 1 are not primes */ |
| 1911 | isprime[0] = isprime[1] = NO; |
| 1912 | |
| 1913 | /* |
| 1914 | * We're going to use the Sieve of Eristosthenes. We start out by |
| 1915 | * assuming everything 2 and greater is prime. |
| 1916 | */ |
| 1917 | for (n = 2; n <= max; n++) { |
| 1918 | isprime[n] = YES; |
| 1919 | } |
| 1920 | |
| 1921 | /* the following loop can stop when it gets to this point */ |
| 1922 | stop = sqrt((double)max) + 1; |
| 1923 | |
| 1924 | prime = 2; |
| 1925 | while (prime <= stop) { |
| 1926 | /* knock out all multiples of this prime number */ |
| 1927 | for (n = 2 * prime; n <= max; n += prime) { |
| 1928 | isprime[n] = NO; |
| 1929 | } |
| 1930 | /* find the next prime */ |
| 1931 | for (n = prime + 1; n <= stop && isprime[n] == NO; n++) |
| 1932 | ; |
| 1933 | prime = n; |
| 1934 | } |
| 1935 | |
| 1936 | return (isprime); |
| 1937 | } |
| 1938 | \f |
| 1939 | /* |
| 1940 | * Name: factor() |
| 1941 | * |
| 1942 | * Abstract: Factor the given number. |
| 1943 | * |
| 1944 | * Returns: array indexed 0 to num, giving the prime factors |
| 1945 | * |
| 1946 | * Description: This function mallocs and returns an array of shorts, indexed |
| 1947 | * from 0 to max. Each element indexed by a prime number tells |
| 1948 | * how many times that prime factor occurs in num. All other |
| 1949 | * elements are 0. The first time it is called, or if num is |
| 1950 | * different from the previous time, it calculates all this, |
| 1951 | * but on other calls it just returns the answer from before. |
| 1952 | */ |
| 1953 | |
| 1954 | short * |
| 1955 | factor(num) |
| 1956 | |
| 1957 | int num; /* the integer to be factored */ |
| 1958 | |
| 1959 | { |
| 1960 | static short *factors = 0; /* array to be malloc'ed */ |
| 1961 | static int oldnum = 0; /* the number passed in previously */ |
| 1962 | short *isprime; /* list of which numbers are prime */ |
| 1963 | int orignum; /* remember original num */ |
| 1964 | int n; /* loop index */ |
| 1965 | |
| 1966 | |
| 1967 | /* if we've just done the same number, just return the answer */ |
| 1968 | if (factors != 0) { |
| 1969 | /* if we've already done the same or more, just return answer*/ |
| 1970 | if (num == oldnum) { |
| 1971 | return (factors); |
| 1972 | } |
| 1973 | /* num changed; free the old array */ |
| 1974 | FREE(factors); |
| 1975 | } |
| 1976 | oldnum = num; /* remember it for next time */ |
| 1977 | |
| 1978 | CALLOCA(short, factors, num + 1); |
| 1979 | |
| 1980 | /* find which numbers up to num are primes */ |
| 1981 | isprime = findprimes(num); |
| 1982 | |
| 1983 | /* |
| 1984 | * For every prime number until "num" is used up, divide it into num |
| 1985 | * as many times as possible, keeping track of how many times. |
| 1986 | */ |
| 1987 | orignum = num; |
| 1988 | for (n = 2; n <= orignum && num > 1; n++) { |
| 1989 | if (isprime[n] == YES) { |
| 1990 | while (num % n == 0) { |
| 1991 | num /= n; |
| 1992 | factors[n]++; |
| 1993 | } |
| 1994 | } |
| 1995 | } |
| 1996 | |
| 1997 | return (factors); |
| 1998 | } |
| 1999 | \f |
| 2000 | |
| 2001 | /* Return the width of the widest note head in the given GRPSYL. */ |
| 2002 | |
| 2003 | double |
| 2004 | widest_head(gs_p) |
| 2005 | |
| 2006 | struct GRPSYL *gs_p; |
| 2007 | |
| 2008 | { |
| 2009 | double widest; /* widest note head in the group */ |
| 2010 | double thiswidth; /* width of current note */ |
| 2011 | int n; /* note index */ |
| 2012 | |
| 2013 | widest = 0.0; |
| 2014 | for (n = 0; n < gs_p->nnotes; n++) { |
| 2015 | thiswidth = width(gs_p->notelist[n].headfont, |
| 2016 | (gs_p->notelist[n].notesize == GS_NORMAL ? |
| 2017 | DFLT_SIZE : SMALLSIZE), |
| 2018 | gs_p->notelist[n].headchar); |
| 2019 | if (thiswidth > widest) { |
| 2020 | widest = thiswidth; |
| 2021 | } |
| 2022 | } |
| 2023 | return(widest); |
| 2024 | } |