1 /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2 * 2006 by Arkkra Enterprises */
3 /* All rights reserved */
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.
20 /* define the default order of stacking for marks */
21 static char Defmarkorder[] = {
33 /* default timesig of 4/4 */
34 static char Dflt_timerep[] = { 4, TSR_SLASH, 4, TSR_END };
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));
44 * Abstract: Init the fixed instances of the SSV structures.
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
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 */
67 * Call zapssv() to release any malloc'ed memory, if any of the
68 * structures have been used before, and mark all fields unused.
72 for (s = 0; s < MAXSTAFFS; s++) {
74 for (v = 0; v < MAXVOICES; v++)
79 * Fill the Score structure with the proper default values, and
80 * mark all its fields as used.
83 Score.scale_factor = DEFSCALE;
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;
102 Score.timerep = Dflt_timerep;
107 Score.division = DEFDIVISION;
108 Score.endingstyle = ENDING_TOP;
109 Score.gridsatend = NO;
111 Score.measnumfamily = BASE_TIMES;
112 Score.measnumfont = FONT_TR;
113 Score.measnumsize = MNUM_SIZE;
114 Score.packfact = DFLTPACKFACT;
115 Score.packexp = DFLTPACKEXP;
118 /* score and staff context */
119 Score.staffscale = DEFSTFSCALE;
121 Score.hidesilent = NO;
122 Score.stafflines = 5;
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;
132 for (v = 0; v < MAXVOICES; v++) {
133 Score.vcombine[v] = 0;
135 Score.vcombinequal = VC_NOOVERLAP;
136 Score.sharps = DEFSHARPS;
138 Score.cancelkey = NO;
139 Score.inttype = PERFECT;
141 Score.addinttype = PERFECT;
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];
160 Score.pedstyle = P_LINE;
161 Score.chorddist = DEFCHORDDIST;
162 Score.dist = DEFDIST;
163 Score.dyndist = DEFDYNDIST;
167 /* score, staff, and voice context */
170 Score.beamfact = DEFBEAMFACT;
171 Score.beammax = DEFBEAMMAX;
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;
188 for (n = 0; n < NUMFLDS; n++) {
189 Score.used[n] = YES; /* all items will be set in Score */
196 * Abstract: Init a fixed instance of the SSV structure to empty.
200 * Description: This function initializes a fixed SSV structure to say that
201 * all fields are unused.
207 struct SSV *s_p; /* pointer to the structure to be zapped */
210 int n; /* loop variable */
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.
219 if (s_p->used[BRACELIST] == YES) {
220 freestaffset(s_p->nbrace, s_p->bracelist);
223 if (s_p->used[BRACKLIST] == YES) {
224 freestaffset(s_p->nbrack, s_p->bracklist);
227 if (s_p->used[BARSTLIST] == YES && s_p->barstlist != 0) {
228 FREE(s_p->barstlist);
231 if (s_p->used[LABEL] == YES && s_p->label != 0) {
235 if (s_p->used[LABEL2] == YES && s_p->label2 != 0) {
239 if (s_p->used[BEAMSTLIST] == YES && s_p->beamstlist != 0) {
240 FREE(s_p->beamstlist);
245 * Mark all fields unused.
247 for (n = 0; n < NUMFLDS; n++) {
253 * Name: freestaffset()
255 * Abstract: Free all malloc'ed memory associated with a staffset list.
259 * Description: This function frees staffset structures, along with their
260 * labels if they exist.
264 freestaffset(num, ss_p)
266 int num; /* how many staffsets are in list? */
267 struct STAFFSET *ss_p; /* pointer to first staffset */
270 int n; /* loop variable */
273 if (ss_p == 0) /* if there is no list, just return */
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 */
282 if (ss_p[n].label2 != 0) { /* if label2, free it */
283 FREE(ss_p[n].label2);
288 FREE(ss_p); /* free the staffset list itself */
292 * Name: asgnstaffset()
294 * Abstract: Set up a staffset list in another SSV structure.
298 * Description: This function sets up a new staffset list identical to
299 * another one, including the labels if they exist.
303 asgnstaffset(num, new_p_p, old_p)
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 */
310 int n; /* loop variable */
313 if (num == 0) /* if there's no old list, nothing to do */
317 * Allocate the new list and point at it.
319 MALLOC(STAFFSET, *new_p_p, num);
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.
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;
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);
334 (*new_p_p)[n].label = 0;
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);
342 (*new_p_p)[n].label2 = 0;
350 * Abstract: Find a field for a staff, using the viewpath.
352 * Returns: pointer to structure containing correct field value
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
365 int s; /* staff number, 1 to MAXSTAFFS; or 0, meaning score */
366 int field; /* the defined symbol for the field desired */
369 static struct SSV phony; /* phony SSV; see below */
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.
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
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
397 if (field == VISIBLE) {
398 int num_voices; /* how many voices on this staff */
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".
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;
410 /* use the score structure; it's always set there */
411 phony.hidesilent = Score.hidesilent;
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 */
421 num_voices = vscheme_voices(svpath(s, VSCHEME)->vscheme);
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
428 if ((Voice_vis[s][1] == YES &&
429 Voice[s-1][0].used[VISIBLE] == YES &&
430 Voice[s-1][0].visible == YES) ||
433 Voice_vis[s][2] == YES &&
434 Voice[s-1][1].used[VISIBLE] == YES &&
435 Voice[s-1][1].visible == YES) ||
438 Voice_vis[s][3] == YES &&
439 Voice[s-1][2].used[VISIBLE] == YES &&
440 Voice[s-1][2].visible == YES)) {
442 /* return phony SSV with YES, ignore real SSV */
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.
452 if ((Voice_vis[s][1] == NO ||
453 Voice[s-1][0].used[VISIBLE] == YES &&
454 Voice[s-1][0].visible == NO) &&
457 (Voice_vis[s][2] == NO ||
458 Voice[s-1][1].used[VISIBLE] == YES &&
459 Voice[s-1][1].visible == NO)) &&
462 (Voice_vis[s][3] == NO ||
463 Voice[s-1][2].used[VISIBLE] == YES &&
464 Voice[s-1][2].visible == NO))) {
466 /* return phony SSV with NO, ignore real SSV */
472 * The command line and the voice(s) aren't forcing the issue.
473 * So fall through to determine the staff's visibility the
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]);
482 /* else use the score structure; it's always set there */
489 * Abstract: Find a field for a voice, using the viewpath.
491 * Returns: pointer to structure containing correct field value
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.
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 */
511 static struct SSV phony; /* phony SSV; see below */
514 if (s == 0 || v == 0)
515 return (svpath(s, field));
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
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.
528 if (field == VISIBLE && (Staff_vis[s] == NO || Voice_vis[s][v] == NO)) {
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().
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]);
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]);
546 /* else use the score structure; it's always set there */
553 * Abstract: Assign fields from an input SSV to a fixed one.
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
576 struct SSV *i_p; /* input SSV structure to be copied from */
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 */
585 f_p = 0; /* to prevent "uninitialized variable" warnings */
588 * Using the selector fields in the input structure, set a pointer to
589 * the fixed structure that is to be populated.
591 switch (i_p->context) {
596 /* silently ignore bogus staff no.; it is caught elsewhere */
597 if (i_p->staffno < 1 || i_p->staffno > MAXSTAFFS) {
600 f_p = &Staff[ i_p->staffno - 1 ];
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) {
608 f_p = &Voice[ i_p->staffno - 1 ][ i_p->voiceno - 1 ];
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.
617 if (i_p->used[SCALE_FACTOR] == YES) {
618 f_p->scale_factor = i_p->scale_factor;
621 if (i_p->used[UNITS] == YES) {
622 f_p->units = i_p->units;
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.
631 if (i_p->used[PAGEHEIGHT] == YES) {
632 if (f_p->panelsperpage == 1) {
633 f_p->pageheight = i_p->pageheight;
635 f_p->pagewidth = i_p->pageheight / 2.0;
639 if (i_p->used[PAGEWIDTH] == YES) {
640 if (f_p->panelsperpage == 1) {
641 f_p->pagewidth = i_p->pagewidth;
643 f_p->pageheight = i_p->pagewidth;
647 if (i_p->used[PANELSPERPAGE] == YES) {
648 /* depending on how this is changing, flip height and width */
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;
659 f_p->panelsperpage = i_p->panelsperpage;
662 if (i_p->used[TOPMARGIN] == YES) {
663 f_p->topmargin = i_p->topmargin;
666 if (i_p->used[BOTMARGIN] == YES) {
667 f_p->botmargin = i_p->botmargin;
670 if (i_p->used[LEFTMARGIN] == YES) {
671 f_p->leftmargin = i_p->leftmargin;
674 if (i_p->used[RIGHTMARGIN] == YES) {
675 f_p->rightmargin = i_p->rightmargin;
678 if (i_p->used[RESTCOMBINE] == YES) {
679 f_p->restcombine = i_p->restcombine;
682 if (i_p->used[FIRSTPAGE] == YES) {
683 f_p->firstpage = i_p->firstpage;
686 if (i_p->used[NUMSTAFF] == YES) {
687 f_p->staffs = i_p->staffs;
689 /* this destroys all staff and voice info */
690 for (s = 0; s < MAXSTAFFS; s++) {
692 for (v = 0; v < MAXVOICES; v++)
693 zapssv(&Voice[s][v]);
697 if (i_p->used[MINSCSEP] == YES) {
698 f_p->minscsep = i_p->minscsep;
701 if (i_p->used[MAXSCSEP] == YES) {
702 f_p->maxscsep = i_p->maxscsep;
705 if (i_p->used[MINSCPAD] == YES) {
706 f_p->minscpad = i_p->minscpad;
709 if (i_p->used[MAXSCPAD] == YES) {
710 f_p->maxscpad = i_p->maxscpad;
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);
720 /* set up new list */
721 f_p->nbrace = i_p->nbrace;
722 asgnstaffset(f_p->nbrace, &f_p->bracelist, i_p->bracelist);
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);
732 /* set up new list */
733 f_p->nbrack = i_p->nbrack;
734 asgnstaffset(f_p->nbrack, &f_p->bracklist, i_p->bracklist);
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);
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];
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;
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
764 f_p->timeunit.d = f_p->timeden;
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;
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
779 if (Score.used[BEAMSTLIST] == YES) {
780 if (Score.nbeam != 0) {
781 FREE(Score.beamstlist);
782 Score.beamstlist = 0;
784 FREE(Score.subbeamstlist);
785 Score.subbeamstlist = 0;
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;
796 FREE(Staff[s].subbeamstlist);
797 Staff[s].subbeamstlist = 0;
798 Staff[s].nsubbeam = 0;
800 Staff[s].used[BEAMSTLIST] = NO;
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;
812 Voice[s][v].used[BEAMSTLIST] = NO;
818 if (i_p->used[DIVISION] == YES) {
819 f_p->division = i_p->division;
822 if (i_p->used[ENDINGSTYLE] == YES) {
823 f_p->endingstyle = i_p->endingstyle;
826 if (i_p->used[GRIDSATEND] == YES) {
827 f_p->gridsatend = i_p->gridsatend;
830 if (i_p->used[MEASNUM] == YES) {
831 f_p->measnum = i_p->measnum;
834 if (i_p->used[MEASNUMFAMILY] == YES) {
835 f_p->measnumfamily = i_p->measnumfamily;
838 if (i_p->used[MEASNUMFONT] == YES) {
839 f_p->measnumfont = i_p->measnumfont;
842 if (i_p->used[MEASNUMSIZE] == YES) {
843 f_p->measnumsize = i_p->measnumsize;
846 if (i_p->used[PACKFACT] == YES) {
847 f_p->packfact = i_p->packfact;
850 if (i_p->used[PACKEXP] == YES) {
851 f_p->packexp = i_p->packexp;
854 if (i_p->used[WARN] == YES) {
855 f_p->warn = i_p->warn;
859 * ========== ITEMS FOR SCORE AND STAFF CONTEXT ===========
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.)
867 #define SETPARM(name, NAME) \
868 switch (i_p->used[NAME]) { \
870 f_p->name = i_p->name; \
871 f_p->used[NAME] = YES; \
874 f_p->used[NAME] = NO; \
876 /* default is NO; do nothing */ \
879 SETPARM(staffscale, STAFFSCALE)
881 switch (i_p->used[STAFFLINES]) {
883 struct SSV *tabnote_p; /* ptr to tabnote fixed SSV */
884 f_p->stafflines = i_p->stafflines;
886 if (i_p->strinfo != 0) { /* tablature */
887 struct SSV *voice_p; /* ptr to a voice's fixed SSV*/
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.
895 f_p->printclef = SS_NORMAL;
896 f_p->strinfo = i_p->strinfo;
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
910 f_p->used[SHARPS] = YES;
912 f_p->inttype = PERFECT;
914 f_p->used[TRANSPOSITION] = YES;
916 f_p->addinttype = PERFECT;
918 f_p->used[ADDTRANSPOSITION] = YES;
921 f_p->used[CLEF] = YES;
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);
931 f_p->subbeamstlist = 0;
932 f_p->used[BEAMSTLIST] = YES;
935 f_p->used[DEFOCT] = YES;
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 ];
941 if (voice_p->used[BEAMSTLIST] == YES) {
942 if (voice_p->nbeam != 0) {
943 FREE(f_p->beamstlist);
944 FREE(f_p->subbeamstlist);
946 voice_p->used[BEAMSTLIST] = NO;
948 voice_p->used[DEFOCT] = NO;
952 * Force fields on the tabnote staff above this tab
955 tabnote_p = &Staff[ i_p->staffno - 2 ];
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.)
966 tabnote_p->stafflines = 5;
967 if (tabnote_p->used[STAFFLINES] == NO)
968 tabnote_p->printclef = SS_NORMAL;
969 tabnote_p->used[STAFFLINES] = YES;
971 } else { /* not tablature */
973 * If this staff used to be tablature, we need to unset
974 * some "used" fields that were forced.
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 ];
985 /* make it non-tablature */
989 f_p->printclef = i_p->printclef;
991 f_p->used[STAFFLINES] = YES;
994 f_p->used[STAFFLINES] = NO;
998 SETPARM(gridswhereused, GRIDSWHEREUSED)
1000 SETPARM(gridscale, GRIDSCALE)
1002 SETPARM(gridfret, GRIDFRET)
1004 SETPARM(numbermrpt, NUMBERMRPT)
1006 SETPARM(printmultnum, PRINTMULTNUM)
1008 SETPARM(restsymmult, RESTSYMMULT)
1010 switch (i_p->used[VSCHEME]) {
1013 * If the vscheme change changes the *number* of voices, we
1014 * have to wipe out the voice information, but otherwise not.
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 */
1023 /* for each staff affected by this change . . . */
1024 for (n = start; n <= stop; n++) {
1025 int oldvoices, newvoices; /* how many before & after */
1027 oldvoices = vscheme_voices(svpath(n + 1,
1029 newvoices = vscheme_voices(i_p->vscheme);
1031 if (oldvoices != newvoices) {
1033 for (v = 0; v < MAXVOICES; v++)
1034 zapssv(&Voice[n][v]);
1038 f_p->vscheme = i_p->vscheme;
1039 f_p->used[VSCHEME] = YES;
1042 f_p->used[VSCHEME] = NO;
1046 switch (i_p->used[VCOMBINE]) {
1048 for (v = 0; v < MAXVOICES; v++) {
1049 f_p->vcombine[v] = i_p->vcombine[v];
1051 f_p->vcombinequal = i_p->vcombinequal;
1052 f_p->used[VCOMBINE] = YES;
1055 f_p->used[VCOMBINE] = NO;
1059 switch (i_p->used[SHARPS]) {
1061 f_p->sharps = i_p->sharps;
1062 f_p->is_minor = i_p->is_minor;
1063 f_p->used[SHARPS] = YES;
1066 f_p->used[SHARPS] = NO;
1070 SETPARM(cancelkey, CANCELKEY)
1072 switch (i_p->used[TRANSPOSITION]) {
1074 f_p->inttype = i_p->inttype;
1075 f_p->intnum = i_p->intnum;
1076 f_p->used[TRANSPOSITION] = YES;
1079 f_p->used[TRANSPOSITION] = NO;
1083 switch (i_p->used[ADDTRANSPOSITION]) {
1085 f_p->addinttype = i_p->addinttype;
1086 f_p->addintnum = i_p->addintnum;
1087 f_p->used[ADDTRANSPOSITION] = YES;
1090 f_p->used[ADDTRANSPOSITION] = NO;
1094 switch (i_p->used[CLEF]) {
1096 f_p->clef = i_p->clef;
1097 f_p->used[CLEF] = YES;
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
1105 if (f_p->clef > ALTO) /* lower than alto */
1107 else if (f_p->clef < TREBLE) /* higher than treble */
1111 f_p->used[DEFOCT] = YES;
1114 f_p->used[DEFOCT] = NO;
1118 SETPARM(rehstyle, REHSTYLE)
1120 SETPARM(fontfamily, FONTFAMILY)
1126 SETPARM(lyricsfamily, LYRICSFAMILY)
1128 SETPARM(lyricsfont, LYRICSFONT)
1130 SETPARM(lyricssize, LYRICSSIZE)
1132 SETPARM(lyricsalign, LYRICSALIGN)
1134 SETPARM(sylposition, SYLPOSITION)
1136 SETPARM(minstsep, MINSTSEP)
1138 SETPARM(staffpad, STAFFPAD)
1140 switch (i_p->used[ABOVEORDER]) {
1142 setorder(PL_ABOVE, i_p, f_p);
1143 f_p->used[ABOVEORDER] = YES;
1146 f_p->used[ABOVEORDER] = NO;
1150 switch (i_p->used[BELOWORDER]) {
1152 setorder(PL_BELOW, i_p, f_p);
1153 f_p->used[BELOWORDER] = YES;
1156 f_p->used[BELOWORDER] = NO;
1160 switch (i_p->used[BETWEENORDER]) {
1162 setorder(PL_BETWEEN, i_p, f_p);
1163 f_p->used[BETWEENORDER] = YES;
1166 f_p->used[BETWEENORDER] = NO;
1170 SETPARM(pedstyle, PEDSTYLE)
1172 SETPARM(chorddist, CHORDDIST)
1176 SETPARM(dyndist, DYNDIST)
1178 switch (i_p->used[LABEL]) {
1180 /* if it was already used, free old label */
1181 if (f_p->used[LABEL] == YES && f_p->label != 0) {
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);
1190 f_p->used[LABEL] = YES;
1193 /* if it was already used, free old label */
1194 if (f_p->used[LABEL] == YES && f_p->label != 0) {
1198 f_p->used[LABEL] = NO;
1202 switch (i_p->used[LABEL2]) {
1204 /* if it was already used, free old label2 */
1205 if (f_p->used[LABEL2] == YES && f_p->label2 != 0) {
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);
1214 f_p->used[LABEL2] = YES;
1217 /* if it was already used, free old label2 */
1218 if (f_p->used[LABEL2] == YES && f_p->label2 != 0) {
1222 f_p->used[LABEL2] = NO;
1227 * ========== ITEMS FOR SCORE, STAFF, AND VOICE CONTEXT ===========
1229 switch (i_p->used[VISIBLE]) {
1231 f_p->visible = i_p->visible;
1232 f_p->hidesilent = i_p->hidesilent;
1233 f_p->used[VISIBLE] = YES;
1236 f_p->used[VISIBLE] = NO;
1239 switch (i_p->used[BEAMSTLIST]) {
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;
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];
1260 for (n = 0; n < f_p->nsubbeam; n++) {
1261 f_p->subbeamstlist[n] = i_p->subbeamstlist[n];
1264 f_p->used[BEAMSTLIST] = YES;
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;
1274 f_p->used[BEAMSTLIST] = NO;
1278 switch (i_p->used[BEAMSLOPE]) {
1280 f_p->beamfact = i_p->beamfact;
1281 f_p->beammax = i_p->beammax;
1282 f_p->used[BEAMSLOPE] = YES;
1285 f_p->used[BEAMSLOPE] = NO;
1291 SETPARM(stemlen, STEMLEN)
1293 SETPARM(stemshorten, STEMSHORTEN)
1295 SETPARM(defoct, DEFOCT)
1297 switch (i_p->used[TIMEUNIT]) {
1299 f_p->timeunit = i_p->timeunit;
1300 f_p->timelist_p = i_p->timelist_p;
1301 f_p->used[TIMEUNIT] = YES;
1304 f_p->used[TIMEUNIT] = NO;
1307 SETPARM(swingunit, SWINGUNIT)
1309 SETPARM(release, RELEASE)
1311 SETPARM(ontheline, ONTHELINE)
1313 SETPARM(tabwhitebox, TABWHITEBOX)
1315 switch (i_p->used[NOTEHEADS]) {
1317 for (n = 0; n < 7; n++) {
1318 f_p->noteheads[n] = i_p->noteheads[n];
1320 f_p->used[NOTEHEADS] = YES;
1323 f_p->used[NOTEHEADS] = NO;
1329 * Name: setssvstate()
1331 * Abstract: Set the static SSVs to the state for a given place in the MML.
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.
1344 setssvstate(mainll_p)
1346 struct MAINLL *mainll_p; /* place in the MLL to stop */
1349 struct MAINLL *mll_p; /* for looping through MLL */
1350 struct TIMEDSSV *tssv_p; /* for looping through TIMEDSSV lists*/
1354 for (mll_p = Mainllhc_p; mll_p != 0 && mll_p != mainll_p;
1355 mll_p = mll_p->next) {
1356 switch (mll_p->str) {
1358 /* assign this normal input SSV */
1359 asgnssv(mll_p->u.ssv_p);
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);
1375 * Abstract: Assign an "order" field from an input SSV to a fixed one.
1379 * Description: This function is called by asgnssv() to assign to the
1380 * appropriate part of the markorder array, based on above, below,
1385 setorder(place, i_p, f_p)
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 */
1392 int m; /* mark (MK_*) */
1393 int stk; /* stacking order */
1397 * First assign all the marks' stacking orders as given. Keep track of
1398 * the highest stacking order number found.
1401 for (m = 0; m < NUM_MARK; m++) {
1402 f_p->markorder[place][m] = i_p->markorder[place][m];
1404 if (f_p->markorder[place][m] > stk)
1405 stk = f_p->markorder[place][m];
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
1415 for (m = 0; m < NUM_MARK; m++) {
1416 if (f_p->markorder[place][m] == 0) {
1417 f_p->markorder[place][m] = ++stk;