| 1 | /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
| 2 | * 2006 by Arkkra Enterprises */ |
| 3 | /* All rights reserved */ |
| 4 | /* |
| 5 | * Name: ssv.c |
| 6 | * |
| 7 | * Description: This file defines the instances of score, staff, and voice |
| 8 | * structures that are used for viewpathing. It also contains |
| 9 | * functions for accessing them. |
| 10 | */ |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <string.h> |
| 14 | |
| 15 | #include "defines.h" |
| 16 | #include "rational.h" |
| 17 | #include "structs.h" |
| 18 | #include "globals.h" |
| 19 | |
| 20 | /* define the default order of stacking for marks */ |
| 21 | static char Defmarkorder[] = { |
| 22 | 1, /* MK_MUSSYM */ |
| 23 | 2, /* MK_OCTAVE */ |
| 24 | 3, /* MK_DYN */ |
| 25 | 3, /* MK_OTHERTEXT */ |
| 26 | 3, /* MK_CHORD */ |
| 27 | 4, /* MK_LYRICS */ |
| 28 | 5, /* MK_ENDING */ |
| 29 | 6, /* MK_REHEARSAL */ |
| 30 | 7, /* MK_PEDAL */ |
| 31 | }; |
| 32 | |
| 33 | /* default timesig of 4/4 */ |
| 34 | static char Dflt_timerep[] = { 4, TSR_SLASH, 4, TSR_END }; |
| 35 | |
| 36 | static void freestaffset P((int num, struct STAFFSET *ss_p)); |
| 37 | static void asgnstaffset P((int num, struct STAFFSET **new_p_p, |
| 38 | struct STAFFSET *old_p)); |
| 39 | static void setorder P((int place, struct SSV *i_p, struct SSV *f_p)); |
| 40 | \f |
| 41 | /* |
| 42 | * Name: initstructs() |
| 43 | * |
| 44 | * Abstract: Init the fixed instances of the SSV structures. |
| 45 | * |
| 46 | * Returns: void |
| 47 | * |
| 48 | * Description: This function initializes all the fixed structures Score, |
| 49 | * Staff[s], and Voice[s][v]. This needs to be done before |
| 50 | * scanning through the main linked list of user input |
| 51 | * structures. |
| 52 | */ |
| 53 | |
| 54 | void |
| 55 | initstructs() |
| 56 | |
| 57 | { |
| 58 | int s; /* staff number */ |
| 59 | int v; /* voice number */ |
| 60 | int n; /* another loop variable */ |
| 61 | int p; /* place (PL_*) */ |
| 62 | int m; /* mark (MK_*) */ |
| 63 | int hs; /* head shape number */ |
| 64 | |
| 65 | |
| 66 | /* |
| 67 | * Call zapssv() to release any malloc'ed memory, if any of the |
| 68 | * structures have been used before, and mark all fields unused. |
| 69 | */ |
| 70 | zapssv(&Score); |
| 71 | |
| 72 | for (s = 0; s < MAXSTAFFS; s++) { |
| 73 | zapssv(&Staff[s]); |
| 74 | for (v = 0; v < MAXVOICES; v++) |
| 75 | zapssv(&Voice[s][v]); |
| 76 | } |
| 77 | |
| 78 | /* |
| 79 | * Fill the Score structure with the proper default values, and |
| 80 | * mark all its fields as used. |
| 81 | */ |
| 82 | /* score context */ |
| 83 | Score.scale_factor = DEFSCALE; |
| 84 | Score.units = INCHES; |
| 85 | Score.pageheight = DEFPAGEHEIGHT; |
| 86 | Score.pagewidth = DEFPAGEWIDTH; |
| 87 | Score.panelsperpage = DEFPANELSPERPAGE; |
| 88 | Score.topmargin = DEFVMARGIN; |
| 89 | Score.botmargin = DEFVMARGIN; |
| 90 | Score.leftmargin = DEFHMARGIN; |
| 91 | Score.rightmargin = DEFHMARGIN; |
| 92 | Score.restcombine = NORESTCOMBINE; |
| 93 | Score.firstpage = NOFIRSTPAGE; |
| 94 | Score.staffs = DEFSTAFFS; |
| 95 | Score.minscsep = DEFMINSCSEP; |
| 96 | Score.maxscsep = DEFMAXSCSEP; |
| 97 | Score.minscpad = DEFMINSCPAD; |
| 98 | Score.maxscpad = DEFMAXSCPAD; |
| 99 | Score.nbrace = 0; |
| 100 | Score.nbrack = 0; |
| 101 | Score.nbarst = 0; |
| 102 | Score.timerep = Dflt_timerep; |
| 103 | Score.timenum = 4; |
| 104 | Score.timeden = 4; |
| 105 | Score.time.n = 1; |
| 106 | Score.time.d = 1; |
| 107 | Score.division = DEFDIVISION; |
| 108 | Score.endingstyle = ENDING_TOP; |
| 109 | Score.gridsatend = NO; |
| 110 | Score.measnum = NO; |
| 111 | Score.measnumfamily = BASE_TIMES; |
| 112 | Score.measnumfont = FONT_TR; |
| 113 | Score.measnumsize = MNUM_SIZE; |
| 114 | Score.packfact = DFLTPACKFACT; |
| 115 | Score.packexp = DFLTPACKEXP; |
| 116 | Score.warn = YES; |
| 117 | |
| 118 | /* score and staff context */ |
| 119 | Score.staffscale = DEFSTFSCALE; |
| 120 | Score.visible = YES; |
| 121 | Score.hidesilent = NO; |
| 122 | Score.stafflines = 5; |
| 123 | Score.strinfo = 0; |
| 124 | Score.printclef = SS_NORMAL; |
| 125 | Score.gridswhereused = NO; |
| 126 | Score.gridscale = DEFGRIDSCALE; |
| 127 | Score.gridfret = DEFGRIDFRET; |
| 128 | Score.numbermrpt = YES; |
| 129 | Score.printmultnum = YES; |
| 130 | Score.restsymmult = NO; |
| 131 | Score.vscheme = V_1; |
| 132 | for (v = 0; v < MAXVOICES; v++) { |
| 133 | Score.vcombine[v] = 0; |
| 134 | } |
| 135 | Score.vcombinequal = VC_NOOVERLAP; |
| 136 | Score.sharps = DEFSHARPS; |
| 137 | Score.is_minor = NO; |
| 138 | Score.cancelkey = NO; |
| 139 | Score.inttype = PERFECT; |
| 140 | Score.intnum = 1; |
| 141 | Score.addinttype = PERFECT; |
| 142 | Score.addintnum = 1; |
| 143 | Score.clef = TREBLE; |
| 144 | Score.rehstyle = RS_BOXED; |
| 145 | Score.fontfamily = BASE_TIMES; |
| 146 | Score.font = FONT_TR; |
| 147 | Score.size = DFLT_SIZE; |
| 148 | Score.lyricsfamily = BASE_TIMES; |
| 149 | Score.lyricsfont = FONT_TR; |
| 150 | Score.lyricssize = DFLT_SIZE; |
| 151 | Score.lyricsalign = DEFLYRICSALIGN; |
| 152 | Score.sylposition = DEFSYLPOSITION; |
| 153 | Score.minstsep = DEFMINSTSEP; |
| 154 | Score.staffpad = DEFSTPAD; |
| 155 | for (p = 0; p < NUM_PLACE; p++) { |
| 156 | for (m = 0; m < NUM_MARK; m++) { |
| 157 | Score.markorder[p][m] = Defmarkorder[m]; |
| 158 | } |
| 159 | } |
| 160 | Score.pedstyle = P_LINE; |
| 161 | Score.chorddist = DEFCHORDDIST; |
| 162 | Score.dist = DEFDIST; |
| 163 | Score.dyndist = DEFDYNDIST; |
| 164 | Score.label = 0; |
| 165 | Score.label2 = 0; |
| 166 | |
| 167 | /* score, staff, and voice context */ |
| 168 | Score.nbeam = 0; |
| 169 | Score.nsubbeam = 0; |
| 170 | Score.beamfact = DEFBEAMFACT; |
| 171 | Score.beammax = DEFBEAMMAX; |
| 172 | Score.pad = DEFPAD; |
| 173 | Score.stemlen = DEFSTEMLEN; |
| 174 | Score.stemshorten = DEFSTEMSHORTEN; |
| 175 | Score.defoct = DEFOCTAVE; |
| 176 | Score.timeunit.n = 1; |
| 177 | Score.timeunit.d = 4; |
| 178 | Score.timelist_p = 0; |
| 179 | Score.swingunit = Zero; |
| 180 | Score.release = DEFRELEASE; |
| 181 | Score.ontheline = YES; |
| 182 | Score.tabwhitebox = NO; |
| 183 | hs = get_shape_num("norm"); |
| 184 | for (n = 0; n < 7; n++) { |
| 185 | Score.noteheads[n] = hs; |
| 186 | } |
| 187 | |
| 188 | for (n = 0; n < NUMFLDS; n++) { |
| 189 | Score.used[n] = YES; /* all items will be set in Score */ |
| 190 | } |
| 191 | } |
| 192 | \f |
| 193 | /* |
| 194 | * Name: zapssv() |
| 195 | * |
| 196 | * Abstract: Init a fixed instance of the SSV structure to empty. |
| 197 | * |
| 198 | * Returns: void |
| 199 | * |
| 200 | * Description: This function initializes a fixed SSV structure to say that |
| 201 | * all fields are unused. |
| 202 | */ |
| 203 | |
| 204 | void |
| 205 | zapssv(s_p) |
| 206 | |
| 207 | struct SSV *s_p; /* pointer to the structure to be zapped */ |
| 208 | |
| 209 | { |
| 210 | int n; /* loop variable */ |
| 211 | |
| 212 | |
| 213 | /* |
| 214 | * If the structure has been used before, we first have to free any |
| 215 | * memory that was malloc'ed. It's okay to check "used" the first |
| 216 | * time, because global variables are set to 0 by the compiler; |
| 217 | * thus, used[X] == NO. |
| 218 | */ |
| 219 | if (s_p->used[BRACELIST] == YES) { |
| 220 | freestaffset(s_p->nbrace, s_p->bracelist); |
| 221 | s_p->bracelist = 0; |
| 222 | } |
| 223 | if (s_p->used[BRACKLIST] == YES) { |
| 224 | freestaffset(s_p->nbrack, s_p->bracklist); |
| 225 | s_p->bracklist = 0; |
| 226 | } |
| 227 | if (s_p->used[BARSTLIST] == YES && s_p->barstlist != 0) { |
| 228 | FREE(s_p->barstlist); |
| 229 | s_p->barstlist = 0; |
| 230 | } |
| 231 | if (s_p->used[LABEL] == YES && s_p->label != 0) { |
| 232 | FREE(s_p->label); |
| 233 | s_p->label = 0; |
| 234 | } |
| 235 | if (s_p->used[LABEL2] == YES && s_p->label2 != 0) { |
| 236 | FREE(s_p->label2); |
| 237 | s_p->label2 = 0; |
| 238 | } |
| 239 | if (s_p->used[BEAMSTLIST] == YES && s_p->beamstlist != 0) { |
| 240 | FREE(s_p->beamstlist); |
| 241 | s_p->beamstlist = 0; |
| 242 | } |
| 243 | |
| 244 | /* |
| 245 | * Mark all fields unused. |
| 246 | */ |
| 247 | for (n = 0; n < NUMFLDS; n++) { |
| 248 | s_p->used[n] = NO; |
| 249 | } |
| 250 | } |
| 251 | \f |
| 252 | /* |
| 253 | * Name: freestaffset() |
| 254 | * |
| 255 | * Abstract: Free all malloc'ed memory associated with a staffset list. |
| 256 | * |
| 257 | * Returns: void |
| 258 | * |
| 259 | * Description: This function frees staffset structures, along with their |
| 260 | * labels if they exist. |
| 261 | */ |
| 262 | |
| 263 | static void |
| 264 | freestaffset(num, ss_p) |
| 265 | |
| 266 | int num; /* how many staffsets are in list? */ |
| 267 | struct STAFFSET *ss_p; /* pointer to first staffset */ |
| 268 | |
| 269 | { |
| 270 | int n; /* loop variable */ |
| 271 | |
| 272 | |
| 273 | if (ss_p == 0) /* if there is no list, just return */ |
| 274 | return; |
| 275 | |
| 276 | /* for each staffset in the list, free labels if present */ |
| 277 | for (n = 0; n < num; n++) { |
| 278 | if (ss_p[n].label != 0) { /* if label, free it */ |
| 279 | FREE(ss_p[n].label); |
| 280 | ss_p[n].label = 0; |
| 281 | } |
| 282 | if (ss_p[n].label2 != 0) { /* if label2, free it */ |
| 283 | FREE(ss_p[n].label2); |
| 284 | ss_p[n].label2 = 0; |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | FREE(ss_p); /* free the staffset list itself */ |
| 289 | } |
| 290 | \f |
| 291 | /* |
| 292 | * Name: asgnstaffset() |
| 293 | * |
| 294 | * Abstract: Set up a staffset list in another SSV structure. |
| 295 | * |
| 296 | * Returns: void |
| 297 | * |
| 298 | * Description: This function sets up a new staffset list identical to |
| 299 | * another one, including the labels if they exist. |
| 300 | */ |
| 301 | |
| 302 | static void |
| 303 | asgnstaffset(num, new_p_p, old_p) |
| 304 | |
| 305 | int num; /* how many staffsets are in list? */ |
| 306 | struct STAFFSET **new_p_p; /* ptr to ptr to first staffset of new list */ |
| 307 | struct STAFFSET *old_p; /* pointer to first staffset of old list */ |
| 308 | |
| 309 | { |
| 310 | int n; /* loop variable */ |
| 311 | |
| 312 | |
| 313 | if (num == 0) /* if there's no old list, nothing to do */ |
| 314 | return; |
| 315 | |
| 316 | /* |
| 317 | * Allocate the new list and point at it. |
| 318 | */ |
| 319 | MALLOC(STAFFSET, *new_p_p, num); |
| 320 | |
| 321 | /* |
| 322 | * Loop through the old list. Wherever there is a label, allocate |
| 323 | * one for the new list. When there isn't, set that pointer to null. |
| 324 | */ |
| 325 | for (n = 0; n < num; n++) { |
| 326 | (*new_p_p)[n].topstaff = old_p[n].topstaff; |
| 327 | (*new_p_p)[n].botstaff = old_p[n].botstaff; |
| 328 | |
| 329 | if (old_p[n].label != 0) { |
| 330 | MALLOCA(char, (*new_p_p)[n].label, |
| 331 | strlen(old_p[n].label) + 1); |
| 332 | (void)strcpy((*new_p_p)[n].label, old_p[n].label); |
| 333 | } else { |
| 334 | (*new_p_p)[n].label = 0; |
| 335 | } |
| 336 | |
| 337 | if (old_p[n].label2 != 0) { |
| 338 | MALLOCA(char, (*new_p_p)[n].label2, |
| 339 | strlen(old_p[n].label2) + 1); |
| 340 | (void)strcpy((*new_p_p)[n].label2, old_p[n].label2); |
| 341 | } else { |
| 342 | (*new_p_p)[n].label2 = 0; |
| 343 | } |
| 344 | } |
| 345 | } |
| 346 | \f |
| 347 | /* |
| 348 | * Name: svpath() |
| 349 | * |
| 350 | * Abstract: Find a field for a staff, using the viewpath. |
| 351 | * |
| 352 | * Returns: pointer to structure containing correct field value |
| 353 | * |
| 354 | * Description: This function, given a staff number and a field number, looks |
| 355 | * down the viewpath to find the first structure where the field |
| 356 | * is set. It returns a pointer to that structure. (However, see |
| 357 | * below for a special kluge for the "visible" field.) |
| 358 | * Note: 0 is allowed for the staff number, and that means use |
| 359 | * the Score value. |
| 360 | */ |
| 361 | |
| 362 | struct SSV * |
| 363 | svpath(s, field) |
| 364 | |
| 365 | int s; /* staff number, 1 to MAXSTAFFS; or 0, meaning score */ |
| 366 | int field; /* the defined symbol for the field desired */ |
| 367 | |
| 368 | { |
| 369 | static struct SSV phony; /* phony SSV; see below */ |
| 370 | |
| 371 | |
| 372 | if (s == 0) |
| 373 | return (&Score); |
| 374 | |
| 375 | /* |
| 376 | * For the "visible" field, special kluges are needed, for two reasons. |
| 377 | * One is that there is a command line option (-s) that overrides the |
| 378 | * visibility requests in the Mup input file. The other is that, even |
| 379 | * though it is a score/staff/voice parameter, it is easier to manage |
| 380 | * visibility at the staff level than at the voice level. Otherwise, |
| 381 | * to know if a staff should be drawn, we would have to check vscheme |
| 382 | * and the visibility state of each voice. |
| 383 | * |
| 384 | * The design is as follows: in mkchords.c, if a voice is to be |
| 385 | * invisible, a measure space is put in place of its original GRPSYL |
| 386 | * list. Users can use svpath() to check if a staff is visible |
| 387 | * instead of having to call vvpath() for its voice(s). The field |
| 388 | * staff_p->visible is set by calling here, so that will also be |
| 389 | * consistent. |
| 390 | * |
| 391 | * If the -s option was used on the command line, only staffs/voices |
| 392 | * listed there are ever allowed to be visible. So although SSVs are |
| 393 | * set as for other score/staff/voice parameters, the results from |
| 394 | * svpath() also consider what the -s option said. In vvpath() this |
| 395 | * is also done. |
| 396 | */ |
| 397 | if (field == VISIBLE) { |
| 398 | int num_voices; /* how many voices on this staff */ |
| 399 | |
| 400 | /* |
| 401 | * In case we are going to return the phony SSV, load the |
| 402 | * hidesilent field into it. Both visible and hidesilent are |
| 403 | * controlled by VISIBLE, but hidesilent is not to be affected |
| 404 | * by the kluges needed for "visible". |
| 405 | */ |
| 406 | /* if the field is set in the staff structure, use that */ |
| 407 | if (Staff[s-1].used[VISIBLE] == YES) { |
| 408 | phony.hidesilent = Staff[s-1].hidesilent; |
| 409 | } else { |
| 410 | /* use the score structure; it's always set there */ |
| 411 | phony.hidesilent = Score.hidesilent; |
| 412 | } |
| 413 | |
| 414 | /* always return NO if the command line says staff invisible */ |
| 415 | if (Staff_vis[s] == NO) { |
| 416 | /* return phony SSV with NO, ignore real SSV */ |
| 417 | phony.visible = NO; |
| 418 | return (&phony); |
| 419 | } |
| 420 | |
| 421 | num_voices = vscheme_voices(svpath(s, VSCHEME)->vscheme); |
| 422 | |
| 423 | /* |
| 424 | * If a voice that the command line is allowing to be visible |
| 425 | * was requested via an SSV to be visible, we must let the |
| 426 | * staff be visible. |
| 427 | */ |
| 428 | if ((Voice_vis[s][1] == YES && |
| 429 | Voice[s-1][0].used[VISIBLE] == YES && |
| 430 | Voice[s-1][0].visible == YES) || |
| 431 | |
| 432 | (num_voices >= 2 && |
| 433 | Voice_vis[s][2] == YES && |
| 434 | Voice[s-1][1].used[VISIBLE] == YES && |
| 435 | Voice[s-1][1].visible == YES) || |
| 436 | |
| 437 | (num_voices >= 3 && |
| 438 | Voice_vis[s][3] == YES && |
| 439 | Voice[s-1][2].used[VISIBLE] == YES && |
| 440 | Voice[s-1][2].visible == YES)) { |
| 441 | |
| 442 | /* return phony SSV with YES, ignore real SSV */ |
| 443 | phony.visible = YES; |
| 444 | return (&phony); |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | * If, for each voice that exists, either the command line is |
| 449 | * forcing it to be invisible or else it was requested via an |
| 450 | * SSV to be invisible, then the staff must be invisible. |
| 451 | */ |
| 452 | if ((Voice_vis[s][1] == NO || |
| 453 | Voice[s-1][0].used[VISIBLE] == YES && |
| 454 | Voice[s-1][0].visible == NO) && |
| 455 | |
| 456 | (num_voices < 2 || |
| 457 | (Voice_vis[s][2] == NO || |
| 458 | Voice[s-1][1].used[VISIBLE] == YES && |
| 459 | Voice[s-1][1].visible == NO)) && |
| 460 | |
| 461 | (num_voices < 3 || |
| 462 | (Voice_vis[s][3] == NO || |
| 463 | Voice[s-1][2].used[VISIBLE] == YES && |
| 464 | Voice[s-1][2].visible == NO))) { |
| 465 | |
| 466 | /* return phony SSV with NO, ignore real SSV */ |
| 467 | phony.visible = NO; |
| 468 | return (&phony); |
| 469 | } |
| 470 | |
| 471 | /* |
| 472 | * The command line and the voice(s) aren't forcing the issue. |
| 473 | * So fall through to determine the staff's visibility the |
| 474 | * normal way. |
| 475 | */ |
| 476 | } |
| 477 | |
| 478 | /* if the field is set in the staff structure, use that */ |
| 479 | if (Staff[s-1].used[field] == YES) |
| 480 | return (&Staff[s-1]); |
| 481 | |
| 482 | /* else use the score structure; it's always set there */ |
| 483 | return (&Score); |
| 484 | } |
| 485 | \f |
| 486 | /* |
| 487 | * Name: vvpath() |
| 488 | * |
| 489 | * Abstract: Find a field for a voice, using the viewpath. |
| 490 | * |
| 491 | * Returns: pointer to structure containing correct field value |
| 492 | * |
| 493 | * Description: This function, given a staff number, voice number on that |
| 494 | * staff, and a field number, looks down the viewpath to find |
| 495 | * the first structure where the field is set. It returns a |
| 496 | * pointer to that structure. (However, see below for a special |
| 497 | * kluge for the "visible" field.) |
| 498 | * Note: 0 is allowed for the voice number, and that means use |
| 499 | * the staff's value. If staff is 0, the Score is used, |
| 500 | * regardless of the voice number. |
| 501 | */ |
| 502 | |
| 503 | struct SSV * |
| 504 | vvpath(s, v, field) |
| 505 | |
| 506 | int s; /* staff number, 1 to MAXSTAFFS; or 0, meaning score */ |
| 507 | int v; /* voice number, 1 to MAXVOICES; or 0, meaning staff */ |
| 508 | int field; /* the defined symbol for the field desired */ |
| 509 | |
| 510 | { |
| 511 | static struct SSV phony; /* phony SSV; see below */ |
| 512 | |
| 513 | |
| 514 | if (s == 0 || v == 0) |
| 515 | return (svpath(s, field)); |
| 516 | |
| 517 | /* |
| 518 | * See the comment in svpath() regarding the "visible" field. There's |
| 519 | * probably no need to call vvpath() for "visible" after mkchords.c has |
| 520 | * run, since voices that are to be invisible are changed to measure |
| 521 | * spaces there. But in mkchords.c itself, and earlier, there is |
| 522 | * sometimes a need. |
| 523 | * |
| 524 | * For the "visible" field, first check the command line to see if this |
| 525 | * voice or its staff must always be invisible. If so, return a phony |
| 526 | * SSV that says that. Otherwise fall through to handle the normal way. |
| 527 | */ |
| 528 | if (field == VISIBLE && (Staff_vis[s] == NO || Voice_vis[s][v] == NO)) { |
| 529 | /* |
| 530 | * Since we are going to force visible to NO, it's irrelevant |
| 531 | * what hidesilent is, so don't bother setting it, unlike what |
| 532 | * we had to do in svpath(). |
| 533 | */ |
| 534 | phony.visible = NO; |
| 535 | return (&phony); |
| 536 | } |
| 537 | |
| 538 | /* if the field is set in the voice structure, use that */ |
| 539 | if (Voice[s-1][v-1].used[field] == YES) |
| 540 | return (&Voice[s-1][v-1]); |
| 541 | |
| 542 | /* else if the field is set in the staff structure, use that */ |
| 543 | if (Staff[s-1].used[field] == YES) |
| 544 | return (&Staff[s-1]); |
| 545 | |
| 546 | /* else use the score structure; it's always set there */ |
| 547 | return (&Score); |
| 548 | } |
| 549 | \f |
| 550 | /* |
| 551 | * Name: asgnssv() |
| 552 | * |
| 553 | * Abstract: Assign fields from an input SSV to a fixed one. |
| 554 | * |
| 555 | * Returns: void |
| 556 | * |
| 557 | * Description: This function is passed an input SSV structure (from an input |
| 558 | * context). For each field where "used" is YES in the input SSV, |
| 559 | * it copies it to the appropriate fixed SSV and sets its "used" |
| 560 | * flag to YES. For each field where "used" is UNSET in the input |
| 561 | * SSV, it sets "used" to NO in the appropriate fixed SSV. |
| 562 | * In some cases, there are side effects, where it also |
| 563 | * alters a lower level structure. E.g., changing the number of |
| 564 | * voices of a staff inits its voice structures. In the case |
| 565 | * of stafflines, setting a staff to be a tablature staff |
| 566 | * automatically automatically forces some other fields to be set |
| 567 | * not only in the given staff, but also in the preceding tabnote |
| 568 | * staff. Note also that the Score "used" flags are already |
| 569 | * always set and don't need to be set here. And Score fields can |
| 570 | * never be unset. |
| 571 | */ |
| 572 | |
| 573 | void |
| 574 | asgnssv(i_p) |
| 575 | |
| 576 | struct SSV *i_p; /* input SSV structure to be copied from */ |
| 577 | |
| 578 | { |
| 579 | struct SSV *f_p; /* ptr to fixed SSV structure to copy into */ |
| 580 | int s, v; /* used for looping through staffs & voices */ |
| 581 | int start, stop; /* loop limits */ |
| 582 | int n; /* another loop variable */ |
| 583 | |
| 584 | |
| 585 | f_p = 0; /* to prevent "uninitialized variable" warnings */ |
| 586 | |
| 587 | /* |
| 588 | * Using the selector fields in the input structure, set a pointer to |
| 589 | * the fixed structure that is to be populated. |
| 590 | */ |
| 591 | switch (i_p->context) { |
| 592 | case C_SCORE: |
| 593 | f_p = &Score; |
| 594 | break; |
| 595 | case C_STAFF: |
| 596 | /* silently ignore bogus staff no.; it is caught elsewhere */ |
| 597 | if (i_p->staffno < 1 || i_p->staffno > MAXSTAFFS) { |
| 598 | return; |
| 599 | } |
| 600 | f_p = &Staff[ i_p->staffno - 1 ]; |
| 601 | break; |
| 602 | case C_VOICE: |
| 603 | /* silently ignore bogus staff/voice; it is caught elsewhere */ |
| 604 | if (i_p->staffno < 1 || i_p->staffno > MAXSTAFFS || |
| 605 | i_p->voiceno < 1 || i_p->voiceno > MAXVOICES) { |
| 606 | return; |
| 607 | } |
| 608 | f_p = &Voice[ i_p->staffno - 1 ][ i_p->voiceno - 1 ]; |
| 609 | break; |
| 610 | } |
| 611 | |
| 612 | /* |
| 613 | * ========== ITEMS FOR SCORE CONTEXT ONLY =========== |
| 614 | * There's no need to set f_p->used[] = YES here; since this is the |
| 615 | * score, those bits are already always YES. |
| 616 | */ |
| 617 | if (i_p->used[SCALE_FACTOR] == YES) { |
| 618 | f_p->scale_factor = i_p->scale_factor; |
| 619 | } |
| 620 | |
| 621 | if (i_p->used[UNITS] == YES) { |
| 622 | f_p->units = i_p->units; |
| 623 | } |
| 624 | |
| 625 | /* |
| 626 | * PAGEHEIGHT, PAGEHEIGHT, and PANELSPERPAGE interact, because when the |
| 627 | * user sets PAGE*, they are referring to the paper, but internally we |
| 628 | * want page* to refer to one "panel" of music, which is a 90 degree |
| 629 | * rotated half of the sheet of paper when panelsperpage is 2. |
| 630 | */ |
| 631 | if (i_p->used[PAGEHEIGHT] == YES) { |
| 632 | if (f_p->panelsperpage == 1) { |
| 633 | f_p->pageheight = i_p->pageheight; |
| 634 | } else { |
| 635 | f_p->pagewidth = i_p->pageheight / 2.0; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | if (i_p->used[PAGEWIDTH] == YES) { |
| 640 | if (f_p->panelsperpage == 1) { |
| 641 | f_p->pagewidth = i_p->pagewidth; |
| 642 | } else { |
| 643 | f_p->pageheight = i_p->pagewidth; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | if (i_p->used[PANELSPERPAGE] == YES) { |
| 648 | /* depending on how this is changing, flip height and width */ |
| 649 | float oldwidth; |
| 650 | if (f_p->panelsperpage == 1 && i_p->panelsperpage == 2) { |
| 651 | oldwidth = f_p->pagewidth; |
| 652 | f_p->pagewidth = f_p->pageheight / 2.0; |
| 653 | f_p->pageheight = oldwidth; |
| 654 | } else if (f_p->panelsperpage == 2 && i_p->panelsperpage == 1) { |
| 655 | oldwidth = f_p->pagewidth; |
| 656 | f_p->pagewidth = f_p->pageheight; |
| 657 | f_p->pageheight = oldwidth * 2.0; |
| 658 | } |
| 659 | f_p->panelsperpage = i_p->panelsperpage; |
| 660 | } |
| 661 | |
| 662 | if (i_p->used[TOPMARGIN] == YES) { |
| 663 | f_p->topmargin = i_p->topmargin; |
| 664 | } |
| 665 | |
| 666 | if (i_p->used[BOTMARGIN] == YES) { |
| 667 | f_p->botmargin = i_p->botmargin; |
| 668 | } |
| 669 | |
| 670 | if (i_p->used[LEFTMARGIN] == YES) { |
| 671 | f_p->leftmargin = i_p->leftmargin; |
| 672 | } |
| 673 | |
| 674 | if (i_p->used[RIGHTMARGIN] == YES) { |
| 675 | f_p->rightmargin = i_p->rightmargin; |
| 676 | } |
| 677 | |
| 678 | if (i_p->used[RESTCOMBINE] == YES) { |
| 679 | f_p->restcombine = i_p->restcombine; |
| 680 | } |
| 681 | |
| 682 | if (i_p->used[FIRSTPAGE] == YES) { |
| 683 | f_p->firstpage = i_p->firstpage; |
| 684 | } |
| 685 | |
| 686 | if (i_p->used[NUMSTAFF] == YES) { |
| 687 | f_p->staffs = i_p->staffs; |
| 688 | |
| 689 | /* this destroys all staff and voice info */ |
| 690 | for (s = 0; s < MAXSTAFFS; s++) { |
| 691 | zapssv(&Staff[s]); |
| 692 | for (v = 0; v < MAXVOICES; v++) |
| 693 | zapssv(&Voice[s][v]); |
| 694 | } |
| 695 | } |
| 696 | |
| 697 | if (i_p->used[MINSCSEP] == YES) { |
| 698 | f_p->minscsep = i_p->minscsep; |
| 699 | } |
| 700 | |
| 701 | if (i_p->used[MAXSCSEP] == YES) { |
| 702 | f_p->maxscsep = i_p->maxscsep; |
| 703 | } |
| 704 | |
| 705 | if (i_p->used[MINSCPAD] == YES) { |
| 706 | f_p->minscpad = i_p->minscpad; |
| 707 | } |
| 708 | |
| 709 | if (i_p->used[MAXSCPAD] == YES) { |
| 710 | f_p->maxscpad = i_p->maxscpad; |
| 711 | } |
| 712 | |
| 713 | if (i_p->used[BRACELIST] == YES) { |
| 714 | /* if it was already used, free old list if present */ |
| 715 | if (f_p->used[BRACELIST] == YES) { |
| 716 | freestaffset(f_p->nbrace, f_p->bracelist); |
| 717 | f_p->bracelist = 0; |
| 718 | } |
| 719 | |
| 720 | /* set up new list */ |
| 721 | f_p->nbrace = i_p->nbrace; |
| 722 | asgnstaffset(f_p->nbrace, &f_p->bracelist, i_p->bracelist); |
| 723 | } |
| 724 | |
| 725 | if (i_p->used[BRACKLIST] == YES) { |
| 726 | /* if it was already used, free old list if present */ |
| 727 | if (f_p->used[BRACKLIST] == YES) { |
| 728 | freestaffset(f_p->nbrack, f_p->bracklist); |
| 729 | f_p->bracklist = 0; |
| 730 | } |
| 731 | |
| 732 | /* set up new list */ |
| 733 | f_p->nbrack = i_p->nbrack; |
| 734 | asgnstaffset(f_p->nbrack, &f_p->bracklist, i_p->bracklist); |
| 735 | } |
| 736 | |
| 737 | if (i_p->used[BARSTLIST] == YES) { |
| 738 | /* if it was already used, free old list if present */ |
| 739 | if (f_p->used[BARSTLIST] == YES && f_p->nbarst != 0) |
| 740 | FREE(f_p->barstlist); |
| 741 | |
| 742 | /* set up new list */ |
| 743 | f_p->nbarst = i_p->nbarst; |
| 744 | /* the +1 is to guard against allocating 0 */ |
| 745 | MALLOC(TOP_BOT, f_p->barstlist, f_p->nbarst + 1); |
| 746 | for (n = 0; n < f_p->nbarst; n++) { |
| 747 | f_p->barstlist[n] = i_p->barstlist[n]; |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | if (i_p->used[TIME] == YES) { |
| 752 | f_p->timenum = i_p->timenum; |
| 753 | f_p->timeden = i_p->timeden; |
| 754 | f_p->timevis = i_p->timevis; |
| 755 | f_p->timerep = i_p->timerep; |
| 756 | f_p->time = i_p->time; |
| 757 | |
| 758 | /* |
| 759 | * Changing the time sig forces a change in default time unit. |
| 760 | * Set it to one "beat" for the score, and unset it for all |
| 761 | * staffs and voices. |
| 762 | */ |
| 763 | f_p->timeunit.n = 1; |
| 764 | f_p->timeunit.d = f_p->timeden; |
| 765 | f_p->timelist_p = 0; |
| 766 | for (s = 0; s < MAXSTAFFS; s++) { |
| 767 | Staff[s].used[TIMEUNIT] = NO; |
| 768 | for (v = 0; v < MAXVOICES; v++) |
| 769 | Voice[s][v].used[TIMEUNIT] = NO; |
| 770 | } |
| 771 | |
| 772 | /* |
| 773 | * Changing the time also destroys all beamstyle lists. |
| 774 | * However, the special empty beamstyle list that was set up |
| 775 | * for a tablature staff must be retained, so that it will |
| 776 | * continue to override any score beamstyle list that may be |
| 777 | * set up later on. |
| 778 | */ |
| 779 | if (Score.used[BEAMSTLIST] == YES) { |
| 780 | if (Score.nbeam != 0) { |
| 781 | FREE(Score.beamstlist); |
| 782 | Score.beamstlist = 0; |
| 783 | Score.nbeam = 0; |
| 784 | FREE(Score.subbeamstlist); |
| 785 | Score.subbeamstlist = 0; |
| 786 | Score.nsubbeam = 0; |
| 787 | } |
| 788 | } |
| 789 | for (s = 0; s < MAXSTAFFS; s++) { |
| 790 | if (Staff[s].used[BEAMSTLIST] == YES && |
| 791 | Staff[s].strinfo == 0) { /* not tablature */ |
| 792 | if (Staff[s].nbeam != 0) { |
| 793 | FREE(Staff[s].beamstlist); |
| 794 | Staff[s].beamstlist = 0; |
| 795 | Staff[s].nbeam = 0; |
| 796 | FREE(Staff[s].subbeamstlist); |
| 797 | Staff[s].subbeamstlist = 0; |
| 798 | Staff[s].nsubbeam = 0; |
| 799 | } |
| 800 | Staff[s].used[BEAMSTLIST] = NO; |
| 801 | } |
| 802 | for (v = 0; v < MAXVOICES; v++) { |
| 803 | if (Voice[s][v].used[BEAMSTLIST] == YES) { |
| 804 | if (Voice[s][v].nbeam != 0) { |
| 805 | FREE(Voice[s][v].beamstlist); |
| 806 | Voice[s][v].beamstlist = 0; |
| 807 | Voice[s][v].nbeam = 0; |
| 808 | FREE(Voice[s][v].subbeamstlist); |
| 809 | Voice[s][v].subbeamstlist = 0; |
| 810 | Voice[s][v].nsubbeam = 0; |
| 811 | } |
| 812 | Voice[s][v].used[BEAMSTLIST] = NO; |
| 813 | } |
| 814 | } |
| 815 | } |
| 816 | } |
| 817 | |
| 818 | if (i_p->used[DIVISION] == YES) { |
| 819 | f_p->division = i_p->division; |
| 820 | } |
| 821 | |
| 822 | if (i_p->used[ENDINGSTYLE] == YES) { |
| 823 | f_p->endingstyle = i_p->endingstyle; |
| 824 | } |
| 825 | |
| 826 | if (i_p->used[GRIDSATEND] == YES) { |
| 827 | f_p->gridsatend = i_p->gridsatend; |
| 828 | } |
| 829 | |
| 830 | if (i_p->used[MEASNUM] == YES) { |
| 831 | f_p->measnum = i_p->measnum; |
| 832 | } |
| 833 | |
| 834 | if (i_p->used[MEASNUMFAMILY] == YES) { |
| 835 | f_p->measnumfamily = i_p->measnumfamily; |
| 836 | } |
| 837 | |
| 838 | if (i_p->used[MEASNUMFONT] == YES) { |
| 839 | f_p->measnumfont = i_p->measnumfont; |
| 840 | } |
| 841 | |
| 842 | if (i_p->used[MEASNUMSIZE] == YES) { |
| 843 | f_p->measnumsize = i_p->measnumsize; |
| 844 | } |
| 845 | |
| 846 | if (i_p->used[PACKFACT] == YES) { |
| 847 | f_p->packfact = i_p->packfact; |
| 848 | } |
| 849 | |
| 850 | if (i_p->used[PACKEXP] == YES) { |
| 851 | f_p->packexp = i_p->packexp; |
| 852 | } |
| 853 | |
| 854 | if (i_p->used[WARN] == YES) { |
| 855 | f_p->warn = i_p->warn; |
| 856 | } |
| 857 | |
| 858 | /* |
| 859 | * ========== ITEMS FOR SCORE AND STAFF CONTEXT =========== |
| 860 | */ |
| 861 | /* |
| 862 | * Most parameters involve just a single field, and have no side |
| 863 | * effects. For this, we can use the following switch statement to |
| 864 | * do the work, for parameters that can exist on staff or voice. |
| 865 | * (Score-only ones don't need it, since that can't be unset.) |
| 866 | */ |
| 867 | #define SETPARM(name, NAME) \ |
| 868 | switch (i_p->used[NAME]) { \ |
| 869 | case YES: \ |
| 870 | f_p->name = i_p->name; \ |
| 871 | f_p->used[NAME] = YES; \ |
| 872 | break; \ |
| 873 | case UNSET: \ |
| 874 | f_p->used[NAME] = NO; \ |
| 875 | break; \ |
| 876 | /* default is NO; do nothing */ \ |
| 877 | } |
| 878 | |
| 879 | SETPARM(staffscale, STAFFSCALE) |
| 880 | |
| 881 | switch (i_p->used[STAFFLINES]) { |
| 882 | case YES: { |
| 883 | struct SSV *tabnote_p; /* ptr to tabnote fixed SSV */ |
| 884 | f_p->stafflines = i_p->stafflines; |
| 885 | |
| 886 | if (i_p->strinfo != 0) { /* tablature */ |
| 887 | struct SSV *voice_p; /* ptr to a voice's fixed SSV*/ |
| 888 | |
| 889 | /* |
| 890 | * This is a tablature staff. Set printclef to normal |
| 891 | * (even though tab isn't particularly "normal"). |
| 892 | * Point f_p->strinfo at the same array that |
| 893 | * i_p->strinfo points at. |
| 894 | */ |
| 895 | f_p->printclef = SS_NORMAL; |
| 896 | f_p->strinfo = i_p->strinfo; |
| 897 | |
| 898 | /* |
| 899 | * Force some other score/staff items to fixed values |
| 900 | * for tab. The parser blocks the user from setting |
| 901 | * these. We need to set them here in the staff SSV to |
| 902 | * override whatever may be in the score SSV. This |
| 903 | * will make it possible to avoid special checks for |
| 904 | * tablature in many places; the right values will be |
| 905 | * set for this staff. Also force score/staff/voice |
| 906 | * items here. |
| 907 | */ |
| 908 | f_p->sharps = 0; |
| 909 | f_p->is_minor = NO; |
| 910 | f_p->used[SHARPS] = YES; |
| 911 | |
| 912 | f_p->inttype = PERFECT; |
| 913 | f_p->intnum = 1; |
| 914 | f_p->used[TRANSPOSITION] = YES; |
| 915 | |
| 916 | f_p->addinttype = PERFECT; |
| 917 | f_p->addintnum = 1; |
| 918 | f_p->used[ADDTRANSPOSITION] = YES; |
| 919 | |
| 920 | f_p->clef = TABCLEF; |
| 921 | f_p->used[CLEF] = YES; |
| 922 | |
| 923 | if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) { |
| 924 | /* if already used, free old list if present */ |
| 925 | FREE(f_p->beamstlist); |
| 926 | FREE(f_p->subbeamstlist); |
| 927 | } |
| 928 | f_p->nbeam = 0; |
| 929 | f_p->beamstlist = 0; |
| 930 | f_p->nsubbeam = 0; |
| 931 | f_p->subbeamstlist = 0; |
| 932 | f_p->used[BEAMSTLIST] = YES; |
| 933 | |
| 934 | f_p->defoct = 4; |
| 935 | f_p->used[DEFOCT] = YES; |
| 936 | |
| 937 | /* blow away the following in tab staff's voices */ |
| 938 | for (v = 0; v < MAXVOICES; v++) { |
| 939 | voice_p = &Voice[ i_p->staffno - 1][ v ]; |
| 940 | |
| 941 | if (voice_p->used[BEAMSTLIST] == YES) { |
| 942 | if (voice_p->nbeam != 0) { |
| 943 | FREE(f_p->beamstlist); |
| 944 | FREE(f_p->subbeamstlist); |
| 945 | } |
| 946 | voice_p->used[BEAMSTLIST] = NO; |
| 947 | } |
| 948 | voice_p->used[DEFOCT] = NO; |
| 949 | } |
| 950 | |
| 951 | /* |
| 952 | * Force fields on the tabnote staff above this tab |
| 953 | * staff. |
| 954 | */ |
| 955 | tabnote_p = &Staff[ i_p->staffno - 2 ]; |
| 956 | |
| 957 | /* |
| 958 | * The parse phase wouldn't let this be another tab |
| 959 | * staff, so we don't need to check for that. But it |
| 960 | * might be a 1-line staff. If so, override it to 5 |
| 961 | * line. If this parameter wasn't set, force printclef |
| 962 | * to normal, but if it was, keep the old value. (We |
| 963 | * might as well allow 5n and 5 drum as well as 5, |
| 964 | * though that would be a weird usage.) |
| 965 | */ |
| 966 | tabnote_p->stafflines = 5; |
| 967 | if (tabnote_p->used[STAFFLINES] == NO) |
| 968 | tabnote_p->printclef = SS_NORMAL; |
| 969 | tabnote_p->used[STAFFLINES] = YES; |
| 970 | |
| 971 | } else { /* not tablature */ |
| 972 | /* |
| 973 | * If this staff used to be tablature, we need to unset |
| 974 | * some "used" fields that were forced. |
| 975 | */ |
| 976 | if (f_p->strinfo != 0) { |
| 977 | f_p->used[SHARPS] = NO; |
| 978 | f_p->used[TRANSPOSITION] = NO; |
| 979 | f_p->used[ADDTRANSPOSITION] = NO; |
| 980 | f_p->used[CLEF] = NO; |
| 981 | f_p->used[BEAMSTLIST] = NO; |
| 982 | f_p->used[DEFOCT] = NO; |
| 983 | tabnote_p = &Staff[ i_p->staffno - 2 ]; |
| 984 | |
| 985 | /* make it non-tablature */ |
| 986 | f_p->strinfo = 0; |
| 987 | } |
| 988 | |
| 989 | f_p->printclef = i_p->printclef; |
| 990 | } |
| 991 | f_p->used[STAFFLINES] = YES; |
| 992 | } break; |
| 993 | case UNSET: |
| 994 | f_p->used[STAFFLINES] = NO; |
| 995 | break; |
| 996 | } |
| 997 | |
| 998 | SETPARM(gridswhereused, GRIDSWHEREUSED) |
| 999 | |
| 1000 | SETPARM(gridscale, GRIDSCALE) |
| 1001 | |
| 1002 | SETPARM(gridfret, GRIDFRET) |
| 1003 | |
| 1004 | SETPARM(numbermrpt, NUMBERMRPT) |
| 1005 | |
| 1006 | SETPARM(printmultnum, PRINTMULTNUM) |
| 1007 | |
| 1008 | SETPARM(restsymmult, RESTSYMMULT) |
| 1009 | |
| 1010 | switch (i_p->used[VSCHEME]) { |
| 1011 | case YES: |
| 1012 | /* |
| 1013 | * If the vscheme change changes the *number* of voices, we |
| 1014 | * have to wipe out the voice information, but otherwise not. |
| 1015 | */ |
| 1016 | if (i_p->context == C_SCORE) { |
| 1017 | start = 0; /* if score, do test for */ |
| 1018 | stop = MAXSTAFFS - 1; /* all staffs */ |
| 1019 | } else { /* C_STAFF */ |
| 1020 | start = stop = i_p->staffno - 1; /* do just this one */ |
| 1021 | } |
| 1022 | |
| 1023 | /* for each staff affected by this change . . . */ |
| 1024 | for (n = start; n <= stop; n++) { |
| 1025 | int oldvoices, newvoices; /* how many before & after */ |
| 1026 | |
| 1027 | oldvoices = vscheme_voices(svpath(n + 1, |
| 1028 | VSCHEME)->vscheme); |
| 1029 | newvoices = vscheme_voices(i_p->vscheme); |
| 1030 | |
| 1031 | if (oldvoices != newvoices) { |
| 1032 | |
| 1033 | for (v = 0; v < MAXVOICES; v++) |
| 1034 | zapssv(&Voice[n][v]); |
| 1035 | } |
| 1036 | } |
| 1037 | |
| 1038 | f_p->vscheme = i_p->vscheme; |
| 1039 | f_p->used[VSCHEME] = YES; |
| 1040 | break; |
| 1041 | case UNSET: |
| 1042 | f_p->used[VSCHEME] = NO; |
| 1043 | break; |
| 1044 | } |
| 1045 | |
| 1046 | switch (i_p->used[VCOMBINE]) { |
| 1047 | case YES: |
| 1048 | for (v = 0; v < MAXVOICES; v++) { |
| 1049 | f_p->vcombine[v] = i_p->vcombine[v]; |
| 1050 | } |
| 1051 | f_p->vcombinequal = i_p->vcombinequal; |
| 1052 | f_p->used[VCOMBINE] = YES; |
| 1053 | break; |
| 1054 | case UNSET: |
| 1055 | f_p->used[VCOMBINE] = NO; |
| 1056 | break; |
| 1057 | } |
| 1058 | |
| 1059 | switch (i_p->used[SHARPS]) { |
| 1060 | case YES: |
| 1061 | f_p->sharps = i_p->sharps; |
| 1062 | f_p->is_minor = i_p->is_minor; |
| 1063 | f_p->used[SHARPS] = YES; |
| 1064 | break; |
| 1065 | case UNSET: |
| 1066 | f_p->used[SHARPS] = NO; |
| 1067 | break; |
| 1068 | } |
| 1069 | |
| 1070 | SETPARM(cancelkey, CANCELKEY) |
| 1071 | |
| 1072 | switch (i_p->used[TRANSPOSITION]) { |
| 1073 | case YES: |
| 1074 | f_p->inttype = i_p->inttype; |
| 1075 | f_p->intnum = i_p->intnum; |
| 1076 | f_p->used[TRANSPOSITION] = YES; |
| 1077 | break; |
| 1078 | case UNSET: |
| 1079 | f_p->used[TRANSPOSITION] = NO; |
| 1080 | break; |
| 1081 | } |
| 1082 | |
| 1083 | switch (i_p->used[ADDTRANSPOSITION]) { |
| 1084 | case YES: |
| 1085 | f_p->addinttype = i_p->addinttype; |
| 1086 | f_p->addintnum = i_p->addintnum; |
| 1087 | f_p->used[ADDTRANSPOSITION] = YES; |
| 1088 | break; |
| 1089 | case UNSET: |
| 1090 | f_p->used[ADDTRANSPOSITION] = NO; |
| 1091 | break; |
| 1092 | } |
| 1093 | |
| 1094 | switch (i_p->used[CLEF]) { |
| 1095 | case YES: |
| 1096 | f_p->clef = i_p->clef; |
| 1097 | f_p->used[CLEF] = YES; |
| 1098 | |
| 1099 | /* |
| 1100 | * Reset the default octave so that the middle line of the |
| 1101 | * staff lies within it. If the user also set octave in |
| 1102 | * this context, this will get changed again later in this |
| 1103 | * function. |
| 1104 | */ |
| 1105 | if (f_p->clef > ALTO) /* lower than alto */ |
| 1106 | f_p->defoct = 3; |
| 1107 | else if (f_p->clef < TREBLE) /* higher than treble */ |
| 1108 | f_p->defoct = 5; |
| 1109 | else |
| 1110 | f_p->defoct = 4; |
| 1111 | f_p->used[DEFOCT] = YES; |
| 1112 | break; |
| 1113 | case UNSET: |
| 1114 | f_p->used[DEFOCT] = NO; |
| 1115 | break; |
| 1116 | } |
| 1117 | |
| 1118 | SETPARM(rehstyle, REHSTYLE) |
| 1119 | |
| 1120 | SETPARM(fontfamily, FONTFAMILY) |
| 1121 | |
| 1122 | SETPARM(font, FONT) |
| 1123 | |
| 1124 | SETPARM(size, SIZE) |
| 1125 | |
| 1126 | SETPARM(lyricsfamily, LYRICSFAMILY) |
| 1127 | |
| 1128 | SETPARM(lyricsfont, LYRICSFONT) |
| 1129 | |
| 1130 | SETPARM(lyricssize, LYRICSSIZE) |
| 1131 | |
| 1132 | SETPARM(lyricsalign, LYRICSALIGN) |
| 1133 | |
| 1134 | SETPARM(sylposition, SYLPOSITION) |
| 1135 | |
| 1136 | SETPARM(minstsep, MINSTSEP) |
| 1137 | |
| 1138 | SETPARM(staffpad, STAFFPAD) |
| 1139 | |
| 1140 | switch (i_p->used[ABOVEORDER]) { |
| 1141 | case YES: |
| 1142 | setorder(PL_ABOVE, i_p, f_p); |
| 1143 | f_p->used[ABOVEORDER] = YES; |
| 1144 | break; |
| 1145 | case UNSET: |
| 1146 | f_p->used[ABOVEORDER] = NO; |
| 1147 | break; |
| 1148 | } |
| 1149 | |
| 1150 | switch (i_p->used[BELOWORDER]) { |
| 1151 | case YES: |
| 1152 | setorder(PL_BELOW, i_p, f_p); |
| 1153 | f_p->used[BELOWORDER] = YES; |
| 1154 | break; |
| 1155 | case UNSET: |
| 1156 | f_p->used[BELOWORDER] = NO; |
| 1157 | break; |
| 1158 | } |
| 1159 | |
| 1160 | switch (i_p->used[BETWEENORDER]) { |
| 1161 | case YES: |
| 1162 | setorder(PL_BETWEEN, i_p, f_p); |
| 1163 | f_p->used[BETWEENORDER] = YES; |
| 1164 | break; |
| 1165 | case UNSET: |
| 1166 | f_p->used[BETWEENORDER] = NO; |
| 1167 | break; |
| 1168 | } |
| 1169 | |
| 1170 | SETPARM(pedstyle, PEDSTYLE) |
| 1171 | |
| 1172 | SETPARM(chorddist, CHORDDIST) |
| 1173 | |
| 1174 | SETPARM(dist, DIST) |
| 1175 | |
| 1176 | SETPARM(dyndist, DYNDIST) |
| 1177 | |
| 1178 | switch (i_p->used[LABEL]) { |
| 1179 | case YES: |
| 1180 | /* if it was already used, free old label */ |
| 1181 | if (f_p->used[LABEL] == YES && f_p->label != 0) { |
| 1182 | FREE(f_p->label); |
| 1183 | f_p->label = 0; |
| 1184 | } |
| 1185 | |
| 1186 | /* set up new label */ |
| 1187 | MALLOCA(char, f_p->label, strlen(i_p->label) + 1); |
| 1188 | (void)strcpy(f_p->label, i_p->label); |
| 1189 | |
| 1190 | f_p->used[LABEL] = YES; |
| 1191 | break; |
| 1192 | case UNSET: |
| 1193 | /* if it was already used, free old label */ |
| 1194 | if (f_p->used[LABEL] == YES && f_p->label != 0) { |
| 1195 | FREE(f_p->label); |
| 1196 | f_p->label = 0; |
| 1197 | } |
| 1198 | f_p->used[LABEL] = NO; |
| 1199 | break; |
| 1200 | } |
| 1201 | |
| 1202 | switch (i_p->used[LABEL2]) { |
| 1203 | case YES: |
| 1204 | /* if it was already used, free old label2 */ |
| 1205 | if (f_p->used[LABEL2] == YES && f_p->label2 != 0) { |
| 1206 | FREE(f_p->label2); |
| 1207 | f_p->label2 = 0; |
| 1208 | } |
| 1209 | |
| 1210 | /* set up new label */ |
| 1211 | MALLOCA(char, f_p->label2, strlen(i_p->label2) + 1); |
| 1212 | (void)strcpy(f_p->label2, i_p->label2); |
| 1213 | |
| 1214 | f_p->used[LABEL2] = YES; |
| 1215 | break; |
| 1216 | case UNSET: |
| 1217 | /* if it was already used, free old label2 */ |
| 1218 | if (f_p->used[LABEL2] == YES && f_p->label2 != 0) { |
| 1219 | FREE(f_p->label2); |
| 1220 | f_p->label2 = 0; |
| 1221 | } |
| 1222 | f_p->used[LABEL2] = NO; |
| 1223 | break; |
| 1224 | } |
| 1225 | |
| 1226 | /* |
| 1227 | * ========== ITEMS FOR SCORE, STAFF, AND VOICE CONTEXT =========== |
| 1228 | */ |
| 1229 | switch (i_p->used[VISIBLE]) { |
| 1230 | case YES: |
| 1231 | f_p->visible = i_p->visible; |
| 1232 | f_p->hidesilent = i_p->hidesilent; |
| 1233 | f_p->used[VISIBLE] = YES; |
| 1234 | break; |
| 1235 | case UNSET: |
| 1236 | f_p->used[VISIBLE] = NO; |
| 1237 | } |
| 1238 | |
| 1239 | switch (i_p->used[BEAMSTLIST]) { |
| 1240 | case YES: |
| 1241 | /* if it was already used, free old list if present */ |
| 1242 | if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) { |
| 1243 | FREE(f_p->beamstlist); |
| 1244 | FREE(f_p->subbeamstlist); |
| 1245 | f_p->beamstlist = 0; |
| 1246 | f_p->subbeamstlist = 0; |
| 1247 | } |
| 1248 | |
| 1249 | /* set up new list */ |
| 1250 | f_p->nbeam = i_p->nbeam; |
| 1251 | f_p->beamrests = i_p->beamrests; |
| 1252 | f_p->beamspaces = i_p->beamspaces; |
| 1253 | f_p->nsubbeam = i_p->nsubbeam; |
| 1254 | /* the +1 is to guard against allocating 0 */ |
| 1255 | MALLOCA(RATIONAL, f_p->beamstlist, f_p->nbeam + 1); |
| 1256 | MALLOCA(RATIONAL, f_p->subbeamstlist, f_p->nsubbeam + 1); |
| 1257 | for (n = 0; n < f_p->nbeam; n++) { |
| 1258 | f_p->beamstlist[n] = i_p->beamstlist[n]; |
| 1259 | } |
| 1260 | for (n = 0; n < f_p->nsubbeam; n++) { |
| 1261 | f_p->subbeamstlist[n] = i_p->subbeamstlist[n]; |
| 1262 | } |
| 1263 | |
| 1264 | f_p->used[BEAMSTLIST] = YES; |
| 1265 | break; |
| 1266 | case UNSET: |
| 1267 | /* if it was already used, free old list if present */ |
| 1268 | if (f_p->used[BEAMSTLIST] == YES && f_p->nbeam != 0) { |
| 1269 | FREE(f_p->beamstlist); |
| 1270 | FREE(f_p->subbeamstlist); |
| 1271 | f_p->beamstlist = 0; |
| 1272 | f_p->subbeamstlist = 0; |
| 1273 | } |
| 1274 | f_p->used[BEAMSTLIST] = NO; |
| 1275 | break; |
| 1276 | } |
| 1277 | |
| 1278 | switch (i_p->used[BEAMSLOPE]) { |
| 1279 | case YES: |
| 1280 | f_p->beamfact = i_p->beamfact; |
| 1281 | f_p->beammax = i_p->beammax; |
| 1282 | f_p->used[BEAMSLOPE] = YES; |
| 1283 | break; |
| 1284 | case UNSET: |
| 1285 | f_p->used[BEAMSLOPE] = NO; |
| 1286 | break; |
| 1287 | } |
| 1288 | |
| 1289 | SETPARM(pad, PAD) |
| 1290 | |
| 1291 | SETPARM(stemlen, STEMLEN) |
| 1292 | |
| 1293 | SETPARM(stemshorten, STEMSHORTEN) |
| 1294 | |
| 1295 | SETPARM(defoct, DEFOCT) |
| 1296 | |
| 1297 | switch (i_p->used[TIMEUNIT]) { |
| 1298 | case YES: |
| 1299 | f_p->timeunit = i_p->timeunit; |
| 1300 | f_p->timelist_p = i_p->timelist_p; |
| 1301 | f_p->used[TIMEUNIT] = YES; |
| 1302 | break; |
| 1303 | case UNSET: |
| 1304 | f_p->used[TIMEUNIT] = NO; |
| 1305 | } |
| 1306 | |
| 1307 | SETPARM(swingunit, SWINGUNIT) |
| 1308 | |
| 1309 | SETPARM(release, RELEASE) |
| 1310 | |
| 1311 | SETPARM(ontheline, ONTHELINE) |
| 1312 | |
| 1313 | SETPARM(tabwhitebox, TABWHITEBOX) |
| 1314 | |
| 1315 | switch (i_p->used[NOTEHEADS]) { |
| 1316 | case YES: |
| 1317 | for (n = 0; n < 7; n++) { |
| 1318 | f_p->noteheads[n] = i_p->noteheads[n]; |
| 1319 | } |
| 1320 | f_p->used[NOTEHEADS] = YES; |
| 1321 | break; |
| 1322 | case UNSET: |
| 1323 | f_p->used[NOTEHEADS] = NO; |
| 1324 | break; |
| 1325 | } |
| 1326 | } |
| 1327 | \f |
| 1328 | /* |
| 1329 | * Name: setssvstate() |
| 1330 | * |
| 1331 | * Abstract: Set the static SSVs to the state for a given place in the MML. |
| 1332 | * |
| 1333 | * Returns: void |
| 1334 | * |
| 1335 | * Description: This function, given any structure from the main linked list, |
| 1336 | * initializes the static SSVs, and then runs through the MLL up |
| 1337 | * to just before that point, assigning SSVs. It assigns not only |
| 1338 | * the SSVs in the MLL, but also the timed SSVs hanging off |
| 1339 | * barlines. You can pass a null pointer, and then it will go |
| 1340 | * through the whole MLL. |
| 1341 | */ |
| 1342 | |
| 1343 | void |
| 1344 | setssvstate(mainll_p) |
| 1345 | |
| 1346 | struct MAINLL *mainll_p; /* place in the MLL to stop */ |
| 1347 | |
| 1348 | { |
| 1349 | struct MAINLL *mll_p; /* for looping through MLL */ |
| 1350 | struct TIMEDSSV *tssv_p; /* for looping through TIMEDSSV lists*/ |
| 1351 | |
| 1352 | |
| 1353 | initstructs(); |
| 1354 | for (mll_p = Mainllhc_p; mll_p != 0 && mll_p != mainll_p; |
| 1355 | mll_p = mll_p->next) { |
| 1356 | switch (mll_p->str) { |
| 1357 | case S_SSV: |
| 1358 | /* assign this normal input SSV */ |
| 1359 | asgnssv(mll_p->u.ssv_p); |
| 1360 | break; |
| 1361 | case S_BAR: |
| 1362 | /* assign each timed SSV, if any */ |
| 1363 | for (tssv_p = mll_p->u.bar_p->timedssv_p; tssv_p != 0; |
| 1364 | tssv_p = tssv_p->next) { |
| 1365 | asgnssv(&tssv_p->ssv); |
| 1366 | } |
| 1367 | break; |
| 1368 | } |
| 1369 | } |
| 1370 | } |
| 1371 | \f |
| 1372 | /* |
| 1373 | * Name: setorder() |
| 1374 | * |
| 1375 | * Abstract: Assign an "order" field from an input SSV to a fixed one. |
| 1376 | * |
| 1377 | * Returns: void |
| 1378 | * |
| 1379 | * Description: This function is called by asgnssv() to assign to the |
| 1380 | * appropriate part of the markorder array, based on above, below, |
| 1381 | * or between. |
| 1382 | */ |
| 1383 | |
| 1384 | static void |
| 1385 | setorder(place, i_p, f_p) |
| 1386 | |
| 1387 | int place; /* PL_* */ |
| 1388 | struct SSV *i_p; /* input SSV structure to be copied from */ |
| 1389 | struct SSV *f_p; /* ptr to fixed SSV structure to copy into */ |
| 1390 | |
| 1391 | { |
| 1392 | int m; /* mark (MK_*) */ |
| 1393 | int stk; /* stacking order */ |
| 1394 | |
| 1395 | |
| 1396 | /* |
| 1397 | * First assign all the marks' stacking orders as given. Keep track of |
| 1398 | * the highest stacking order number found. |
| 1399 | */ |
| 1400 | stk = 0; |
| 1401 | for (m = 0; m < NUM_MARK; m++) { |
| 1402 | f_p->markorder[place][m] = i_p->markorder[place][m]; |
| 1403 | |
| 1404 | if (f_p->markorder[place][m] > stk) |
| 1405 | stk = f_p->markorder[place][m]; |
| 1406 | } |
| 1407 | |
| 1408 | /* |
| 1409 | * For every mark type that the user didn't list, the stacking order is |
| 1410 | * now 0. Set all these to default settings, higher than all the ones |
| 1411 | * the user listed, but in the same order as Defmarkorder. They will |
| 1412 | * all be separate numbers, none set equal, unlike Defmarkorder, where |
| 1413 | * some are equal. |
| 1414 | */ |
| 1415 | for (m = 0; m < NUM_MARK; m++) { |
| 1416 | if (f_p->markorder[place][m] == 0) { |
| 1417 | f_p->markorder[place][m] = ++stk; |
| 1418 | } |
| 1419 | } |
| 1420 | } |