chiark / gitweb /
Merge branch 'arkkra' into shiny
[mup] / mup / mup / ssv.c
CommitLineData
69695f33
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 */
21static 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 */
34static char Dflt_timerep[] = { 4, TSR_SLASH, 4, TSR_END };
35
36static void freestaffset P((int num, struct STAFFSET *ss_p));
37static void asgnstaffset P((int num, struct STAFFSET **new_p_p,
38 struct STAFFSET *old_p));
39static 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
54void
55initstructs()
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
204void
205zapssv(s_p)
206
207struct 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
263static void
264freestaffset(num, ss_p)
265
266int num; /* how many staffsets are in list? */
267struct 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
302static void
303asgnstaffset(num, new_p_p, old_p)
304
305int num; /* how many staffsets are in list? */
306struct STAFFSET **new_p_p; /* ptr to ptr to first staffset of new list */
307struct 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
362struct SSV *
363svpath(s, field)
364
365int s; /* staff number, 1 to MAXSTAFFS; or 0, meaning score */
366int 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
503struct SSV *
504vvpath(s, v, field)
505
506int s; /* staff number, 1 to MAXSTAFFS; or 0, meaning score */
507int v; /* voice number, 1 to MAXVOICES; or 0, meaning staff */
508int 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
573void
574asgnssv(i_p)
575
576struct 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
1343void
1344setssvstate(mainll_p)
1345
1346struct 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
1384static void
1385setorder(place, i_p, f_p)
1386
1387int place; /* PL_* */
1388struct SSV *i_p; /* input SSV structure to be copied from */
1389struct 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}