Commit | Line | Data |
---|---|---|
fac14bbe MW |
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 | } |