2 /* Copyright (c) 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* functions to deal with brace/bracket lists, to make sure they don't
6 * overlap, and then to place the labels to minimize the space they use. */
12 /* padding between labels in inches. **** eventually should adjust padding
13 * based on size??? ***/
14 #define LABELPAD 0.125
16 /* information to be able to determine overlaps in the brace/bracket lists */
17 static struct BRAC_INFO
{
18 struct STAFFSET
*staffset_p
; /* bracelist or bracklist item */
19 int bractype
; /* BRACELIST or BRACKLIST */
20 struct BRAC_INFO
*nested_p
; /* pointer to another brace/bracket
21 * item, which has its top on the
22 * same staff, and presumably
23 * is nested inside this one */
24 struct BRAC_INFO
*nested_by_p
; /* if this one is nested, pointer
25 * to what it is nested by, else NULL */
26 short nestlevel
; /* how many levels deep */
27 short topvisstaff
; /* top visible staff in range */
28 short botvisstaff
; /* bottom visible staff in range */
29 } *Brac_info_p
[MAXSTAFFS
+ 1];
32 /* information about a label, either for a staff or group. */
34 char *label
; /* text of the label */
35 float width
; /* strwidth(label) */
36 float west
; /* relative distance of left edge of label
37 * from the line between the labels and the
38 * braces/brackets. This will be negative */
39 int is_staff_label
; /* YES for staff label, NO for group */
40 struct LABELINFO
*next
;/* linked list of labels at same y location */
43 /* information about all the labels that end up being printed left of a
44 * specific staff or between that staff and the one below it. */
46 short staffno
; /* which staff */
47 struct LABELINFO
*label_p
; /* list of labels to be printed to
48 * the left of this staff */
49 struct LABELINFO
*btwnlabel_p
; /* list of labels to be printed
50 * between this staff and the one
52 short pad
; /* how many levels of labels
53 * have been put on this staff, either
54 * on the staff itself or on one or
55 * more other staffs that are
56 * grouped with this one */
58 static struct LABELLIST Labellist
[MAXSTAFFS
+ 1];
60 static short Numvis
; /* how many staffs currently visible */
61 static short Maxlevels
; /* maximum number of nesting levels */
62 static float Nested_brace_adjust
= 0.0; /* brace outside a bracket needs
63 * some extra space to look good. */
66 /* static functions */
67 static void free_brac_info
P((struct BRAC_INFO
*brac_info_p
));
68 static void set_brac_info
P((struct STAFFSET
*staffset_p
, int bractype
));
69 static int check_brac_overlap
P((struct BRAC_INFO
*brac_info_p
));
70 static void setnestlevel
P((struct BRAC_INFO
*brac_p
,
71 struct BRAC_INFO
*nested_by_p
));
72 static void place_labels
P((struct MAINLL
*mll_p
,
73 struct MAINLL
*prev_feed_mll_p
));
74 static void init_labellist
P((void));
75 static void free_label
P((struct LABELINFO
*label_p
));
76 static struct LABELINFO
*newlabelinfo
P((char *label
, int is_staff_label
));
77 static void grouplabel
P((struct BRAC_INFO
*brac_p
, int do_nested
,
78 struct MAINLL
*mll_p
, struct MAINLL
*prev_feed_mll_p
));
79 static double west_adjust
P((struct MAINLL
*mll_p
,
80 struct MAINLL
*prev_feed_mll_p
));
81 static struct MAINLL
*find_prev_feed_mll_p
P((struct MAINLL
*mll_p
));
82 static char * label4staff
P((struct MAINLL
*mll_p
, int s
,
83 struct MAINLL
*prev_feed_mll_p
));
84 static char * label4group
P((struct MAINLL
*mll_p
, struct BRAC_INFO
*brac_p
,
85 struct MAINLL
*prev_feed_mll_p
));
86 static double dflt_label_width
P((struct MAINLL
*mll_p
,
87 struct MAINLL
*prev_feed_mll_p
));
91 /* check for overlap between brace and bracket lists. Return YES if okay, NO
92 * if there is something illegal */
95 brac_check (bracelist_p
, nbrace
, bracklist_p
, nbrack
)
97 struct STAFFSET
*bracelist_p
;
98 int nbrace
; /* how many items in bracelist_p */
99 struct STAFFSET
*bracklist_p
;
100 int nbrack
; /* how many items in bracklist_p */
103 register int s
; /* staff index into Brac_info_p */
104 register int n
; /* index into staffset */
105 int retval
= 0; /* return from check_brac_overlap() */
106 static int first_time
= YES
; /* flag for if first time this function
110 debug(4, "brac_check");
112 /* initialize table */
113 for (s
= 1; s
<= Score
.staffs
; s
++) {
114 if (first_time
== NO
) {
115 /* only try to free if we know item has been properly
116 * initialized, in case this is ever run on some system
117 * that doesn't initialize pointer arrays to null ptrs */
118 free_brac_info(Brac_info_p
[s
]);
120 Brac_info_p
[s
] = (struct BRAC_INFO
*) 0;
125 /* Go through each list, attaching each to table slot of its top staff.
127 for (n
= 0; n
< nbrace
; n
++) {
128 set_brac_info( &(bracelist_p
[n
]), BRACELIST
);
130 for (n
= 0; n
< nbrack
; n
++) {
131 set_brac_info( &(bracklist_p
[n
]), BRACKLIST
);
134 /* now check each staff for possible overlap */
135 for (s
= 1; s
<= Score
.staffs
; s
++) {
136 if (Brac_info_p
[s
] == (struct BRAC_INFO
*) 0) {
137 /* no braces or brackets, so can't be any overlap */
141 retval
+= check_brac_overlap (Brac_info_p
[s
]);
144 return(retval
== 0 ? YES
: NO
);
148 /* recursively free a linked list of BRAC_INFO structs */
151 free_brac_info(brac_info_p
)
153 struct BRAC_INFO
*brac_info_p
; /* the list to free */
156 if (brac_info_p
== (struct BRAC_INFO
*) 0) {
160 free_brac_info(brac_info_p
->nested_p
);
165 /* save information about a brace/bracket STAFFSET and link onto list for its
169 set_brac_info (staffset_p
, bractype
)
171 struct STAFFSET
*staffset_p
; /* staffs to group together */
172 int bractype
; /* BRACELIST or BRACKLIST */
175 struct BRAC_INFO
*new_p
; /* info to be saved */
176 int s
; /* staff num of top staff of staffset */
179 /* record information */
180 MALLOC(BRAC_INFO
, new_p
, 1);
181 new_p
->staffset_p
= staffset_p
;
182 new_p
->bractype
= bractype
;
183 new_p
->nested_by_p
= (struct BRAC_INFO
*) 0;
184 new_p
->nestlevel
= 0;
186 /* link into list off of table */
187 s
= staffset_p
->topstaff
;
188 new_p
->nested_p
= Brac_info_p
[s
];
189 Brac_info_p
[s
] = new_p
;
193 /* check the brace/bracket information for one staff for overlap. Return
194 * number of errors found */
197 check_brac_overlap (brac_info_p
)
199 struct BRAC_INFO
*brac_info_p
;
205 if (brac_info_p
== (struct BRAC_INFO
*) 0) {
210 /* if no nesting, don't need to do those checks */
211 if (brac_info_p
->nested_p
!= (struct BRAC_INFO
*) 0) {
213 /* braces can't have anything nested inside them */
214 if (brac_info_p
->bractype
== BRACELIST
) {
215 yyerror("nesting inside a brace not allowed");
219 /* brace on top of bracket needs extra space */
220 if (brac_info_p
->nested_p
->bractype
== BRACELIST
) {
221 Nested_brace_adjust
= STEPSIZE
;
224 /* check that nested range is a proper subset */
225 if (brac_info_p
->nested_p
->staffset_p
->botstaff
226 >= brac_info_p
->staffset_p
->botstaff
) {
227 yyerror("nested brackets must be subsets of other brackets");
231 setnestlevel(brac_info_p
->nested_p
, brac_info_p
);
234 /* see if this one overlaps with groups
235 * defined previously */
236 for (s
= brac_info_p
->staffset_p
->topstaff
+ 1;
237 s
<= brac_info_p
->staffset_p
->botstaff
; s
++) {
239 if (Brac_info_p
[s
] == (struct BRAC_INFO
*) 0) {
243 /* if brace is being nested by something else,
244 * overlap is illegal */
245 if (brac_info_p
->bractype
== BRACELIST
) {
246 yyerror("brace overlap not allowed");
250 /* if bottom of this staffset is greater than bottom of the one
251 * we are checking, there is illegal overlap */
252 if (Brac_info_p
[s
]->staffset_p
->botstaff
253 > brac_info_p
->staffset_p
->botstaff
) {
254 yyerror("overlapping brackets are not nested");
258 /* remember who nests this one */
259 setnestlevel(Brac_info_p
[s
], brac_info_p
);
263 return (check_brac_overlap (brac_info_p
->nested_p
));
267 /* when one bracket is nested inside another, record that fact */
270 setnestlevel(brac_p
, nested_by_p
)
272 struct BRAC_INFO
*brac_p
; /* set nesting here */
273 struct BRAC_INFO
*nested_by_p
; /* brac_p is nested by this one */
276 brac_p
->nested_by_p
= nested_by_p
;
277 brac_p
->nestlevel
= nested_by_p
->nestlevel
+ 1;
279 /* keep track of deepest nesting level */
280 if (brac_p
->nestlevel
> Maxlevels
) {
281 Maxlevels
= brac_p
->nestlevel
;
288 * find which staff the label should go on based on visible
290 * Determine placement of staff labels, then nested, then outer.
294 place_labels(mll_p
, prev_feed_mll_p
)
296 struct MAINLL
*mll_p
; /* current place in main list, used to determine
297 * whether to use label or label2. */
298 struct MAINLL
*prev_feed_mll_p
; /* actual or proposed location of prev FEED */
301 int s
; /* index through staffs */
302 int count
; /* how many labels */
303 char *label
; /* the label being processed */
304 struct LABELINFO
*lab_p
;/* info about label */
308 lab_p
= (struct LABELINFO
*) 0;
310 /* put the staff labels on the label list. While we're at it, count
311 * up the number of staffs that are currently visible */
312 for (count
= Numvis
= 0, s
= 1; s
<= Score
.staffs
; s
++) {
313 if (svpath(s
, VISIBLE
)->visible
== NO
) {
317 /* use label or label2 as appropriate */
318 if ((label
= label4staff(mll_p
, s
, prev_feed_mll_p
)) != 0) {
319 lab_p
= newlabelinfo(label
, YES
);
322 /* if there was a label, save info about it */
323 if (lab_p
!= (struct LABELINFO
*) 0) {
325 /* staff labels always go as far east as possible */
326 /* Adjust by staffscale, but get from SSV, since
327 * Stepsize won't be up to date. */
328 lab_p
->west
= (-(lab_p
->width
) - STEPSIZE
)
329 * svpath(s
, STAFFSCALE
)->staffscale
;
332 lab_p
->next
= Labellist
[Numvis
].label_p
;
333 Labellist
[Numvis
].label_p
= lab_p
;
335 /* count up number of staff labels */
338 /* re-init for next trip through loop */
339 lab_p
= (struct LABELINFO
*) 0;
342 Labellist
[Numvis
].staffno
= (short) s
;
344 /* we now know there is one more staff visible */
348 /* if there were any labels, mark all staffs as needing padding
349 * before placing another label. If there were no staff labels,
350 * group labels will go as far east as possible, otherwise the
351 * group labels will be leftward a bit. */
353 for (s
= 0; s
< Numvis
; s
++) {
354 (Labellist
[s
].pad
)++;
358 /* do all nested group labels */
359 for (s
= 1; s
<= Score
.staffs
; s
++) {
360 grouplabel(Brac_info_p
[s
], YES
, mll_p
, prev_feed_mll_p
);
363 /* do all non-nested group labels */
364 for (s
= 1; s
<= Score
.staffs
; s
++) {
365 grouplabel(Brac_info_p
[s
], NO
, mll_p
, prev_feed_mll_p
);
370 /* initialize label list. Free any information currently in the list and
371 * mark everything as empty */
377 register int s
; /* index through label list */
380 for (s
= 0; s
<= Numvis
; s
++) {
381 free_label(Labellist
[s
].label_p
);
382 free_label(Labellist
[s
].btwnlabel_p
);
383 Labellist
[s
].label_p
= Labellist
[s
].btwnlabel_p
384 = (struct LABELINFO
*) 0;
385 Labellist
[s
].pad
= 0;
391 /* recursively free linked list of LABELINFO structs */
396 struct LABELINFO
*label_p
; /* free this list */
399 if (label_p
== (struct LABELINFO
*) 0) {
403 free_label(label_p
->next
);
408 /* allocate a new LABELINFO struct and fill in the label and width. Initialize
411 static struct LABELINFO
*
412 newlabelinfo(label
, is_staff_label
)
414 char *label
; /* text of the label */
415 int is_staff_label
; /* YES or NO */
418 struct LABELINFO
*new_p
; /* newly allocate place to save info */
421 MALLOC(LABELINFO
, new_p
, 1);
422 new_p
->label
= label
;
424 new_p
->width
= strwidth(label
);
425 new_p
->is_staff_label
= is_staff_label
;
426 new_p
->next
= (struct LABELINFO
*) 0;
431 /* do placement of group labels */
434 grouplabel(brac_p
, do_nested
, mll_p
, prev_feed_mll_p
)
436 struct BRAC_INFO
*brac_p
; /* info about group of staffs to do */
437 int do_nested
; /* if YES, process nested staff group. If NO,
438 * process non-nested */
439 struct MAINLL
*mll_p
; /* used to decide if to use label or label2 */
440 struct MAINLL
*prev_feed_mll_p
; /* actual or proposed previous FEED */
443 struct STAFFSET
*staffset_p
; /* staffs/label in group */
444 char *label
; /* label for group */
445 int index
; /* into Labellist */
446 int topindex
, botindex
; /* index into Labellist of where
447 * group range top & bottom visible
449 int labindex
; /* index into Labellist of staff where
451 struct LABELINFO
*lab_p
; /* information about group label */
452 struct LABELINFO
**lab_p_p
; /* where to insert label info */
455 if (brac_p
== (struct BRAC_INFO
*) 0) {
460 if (do_nested
== YES
) {
462 grouplabel(brac_p
->nested_p
, do_nested
, mll_p
, prev_feed_mll_p
);
463 if (brac_p
->nested_by_p
== (struct BRAC_INFO
*) 0) {
467 else if (brac_p
->nested_by_p
!= (struct BRAC_INFO
*) 0) {
471 /* we'll probably need the staffset info a lot, so get pointer to it */
472 staffset_p
= brac_p
->staffset_p
;
474 /* Find index in Labellist of top
475 * and bottom visible staffs of the range */
476 for (topindex
= botindex
= -1, index
= 0; index
< Numvis
; index
++) {
477 if (topindex
== -1 && staffset_p
->topstaff
478 <= Labellist
[index
].staffno
) {
481 if (staffset_p
->botstaff
>= Labellist
[index
].staffno
) {
486 /* see if there were some visible staffs in this group */
487 if (topindex
!= -1 && botindex
!= -1 && botindex
>= topindex
) {
489 brac_p
->topvisstaff
= Labellist
[topindex
].staffno
;
490 brac_p
->botvisstaff
= Labellist
[botindex
].staffno
;
492 /* figure out which label to use, if any */
493 if ((label
= label4group(mll_p
, brac_p
, prev_feed_mll_p
))
498 /* find index in list of visible staffs where label should
499 * go. If even number of visible staffs in range, label
500 * goes between two staffs */
501 labindex
= (topindex
+ botindex
) / 2;
502 if ((botindex
- topindex
) & 1) {
503 lab_p_p
= &(Labellist
[labindex
].btwnlabel_p
);
506 lab_p_p
= &(Labellist
[labindex
].label_p
);
509 lab_p
= newlabelinfo(label
, NO
);
511 /* put as far east as possible */
512 lab_p
->west
= - (lab_p
->width
);
514 lab_p
->west
-= Labellist
[labindex
].pad
* LABELPAD
;
517 lab_p
->next
= *lab_p_p
;
520 /* add padding to all visible staffs in the group range */
521 for ( ; topindex
<= botindex
; topindex
++) {
522 Labellist
[topindex
].pad
++;
526 /* all staffs in group are invisible */
527 brac_p
->topvisstaff
= 0;
532 /* determine total width of labels. This is how much to add to
533 * relative west to get absolute location from left margin */
536 west_adjust(mll_p
, prev_feed_mll_p
)
538 struct MAINLL
*mll_p
; /* actual or proposed FEED location,
539 * used to decide if to use label or label2 */
540 struct MAINLL
*prev_feed_mll_p
; /* actual or proposed location of preceeding
541 * FEED, used for label/label2 decision */
544 register int s
; /* index */
545 double minwest
= 0.0; /* farthest west distance */
548 /* find westernmost label */
549 for (s
= 0; s
< Numvis
; s
++) {
550 if (Labellist
[s
].label_p
!= (struct LABELINFO
*) 0) {
551 if (Labellist
[s
].label_p
->west
< minwest
) {
552 minwest
= Labellist
[s
].label_p
->west
;
555 if (Labellist
[s
].btwnlabel_p
!= (struct LABELINFO
*) 0) {
556 if (Labellist
[s
].btwnlabel_p
->west
< minwest
) {
557 minwest
= Labellist
[s
].btwnlabel_p
->west
;
562 /* check for need to use default label on first score.
563 * If default label is needed, it creates an indent. */
564 if (minwest
== 0.0) {
565 return(dflt_label_width(mll_p
, prev_feed_mll_p
));
572 /* return width of braces/brackets and their labels */
575 width_left_of_score(mll_p
)
577 struct MAINLL
*mll_p
; /* FEED, used to decide if to use label or label2 */
580 return(pwidth_left_of_score(mll_p
, find_prev_feed_mll_p(mll_p
)));
584 pwidth_left_of_score(mll_p
, prev_feed_mll_p
)
586 struct MAINLL
*mll_p
; /* actual or proposed location of current FEED,
587 * used to decide if to use label or label2 */
588 struct MAINLL
*prev_feed_mll_p
; /* actual or proposed location of prev FEED */
592 int n
; /* index through brac*lists */
593 int s
; /* staff index */
594 int hasbracs
; /* YES if there are visible brackets/braces */
597 if (brac_check(Score
.bracelist
, Score
.nbrace
, Score
.bracklist
,
598 Score
.nbrack
) == NO
) {
599 /* we should have exited before */
600 pfatal("illegal brace/bracket ranges");
602 /* call functions to determine the placement of all labels and
603 * save that information in the Labellist, then determine how
604 * wide the labels plus braces and brackets are */
605 place_labels(mll_p
, prev_feed_mll_p
);
606 westadj
= west_adjust(mll_p
, prev_feed_mll_p
);
608 /* total is space for the labels (the westadj),
609 * the braces/brackets themselves (based on Maxlevels),
610 * and 2 stepsizes of padding to left of score before brace/brack,
611 * plus special adjustment for brace on top of bracket, if any */
612 /* See if there are any visible brackets/braces.
613 * If so, we'll need to allow space for them, otherwise not. */
615 for (n
= 0; n
< Score
.nbrace
&& hasbracs
== NO
; n
++) {
616 for (s
= Score
.bracelist
[n
].topstaff
;
617 s
<= Score
.bracelist
[n
].botstaff
; s
++){
618 if (svpath(s
, VISIBLE
)->visible
== YES
) {
624 for (n
= 0; n
< Score
.nbrack
&& hasbracs
== NO
; n
++) {
625 for (s
= Score
.bracklist
[n
].topstaff
;
626 s
<= Score
.bracklist
[n
].botstaff
; s
++){
627 if (svpath(s
, VISIBLE
)->visible
== YES
) {
634 if (hasbracs
== YES
) {
635 return(westadj
+ ((Maxlevels
+ 2) * 2.0 * STDPAD
)
636 + (2.0 * STEPSIZE
) + Nested_brace_adjust
);
644 /* print braces/brackets and their labels, Return YES if there were braces or
645 * brackets, NO if not. */
648 pr_brac(is_restart
, x_offset
, mll_p
)
650 int is_restart
; /* YES if being called due to restart */
651 double x_offset
; /* where to print, if is_restart == YES */
652 struct MAINLL
*mll_p
; /* for FEED for possible margin override, and to
653 * decide if to use label or label2 */
656 register int li
; /* index into Labellist */
657 register int s
; /* staff index */
658 struct LABELINFO
*lab_p
; /* info about a label */
659 struct LABELINFO
*l_p
; /* for finding y adjust for overlaps */
660 double y_adjust
; /* for overlapping labels */
661 struct BRAC_INFO
*brac_p
; /* info about brace or bracket */
662 double adj
; /* how much to adjust relative west */
664 int eff_stafflines
; /* how many stafflines there effectively
665 * are, counting the extra space around
666 * staffs with a very small number
668 double tab_adjust
; /* to adjust for TABRATIO */
669 double eff_stepsize
; /* STEPSIZE adjusted for staffscale */
671 int printed_brac
= NO
; /* if printed any braces/brackets */
672 struct MAINLL
*prev_feed_mll_p
; /* previous FEED */
675 debug(512, "pr_brac");
677 /* figure out where to place everything */
678 (void) brac_check(Score
.bracelist
, Score
.nbrace
, Score
.bracklist
,
680 prev_feed_mll_p
= find_prev_feed_mll_p(mll_p
);
681 place_labels(mll_p
, prev_feed_mll_p
);
682 if (is_restart
== NO
) {
683 adj
= west_adjust(mll_p
, prev_feed_mll_p
)
684 + eff_leftmargin(mll_p
);
686 /* print labels on visible staffs */
687 for (li
= 0; li
< Numvis
; li
++) {
689 /* print labels to go by this staff */
690 for (lab_p
= Labellist
[li
].label_p
;
691 lab_p
!= (struct LABELINFO
*) 0;
692 lab_p
= lab_p
->next
) {
693 if (lab_p
->is_staff_label
== YES
) {
694 /* Have to adjust by staffscale.
695 * We can't change the label
696 * in the SSV itself because that
697 * would cause problems, so make a copy
698 * and adjust that, then free it
699 * when we are done with it.
700 * Have to get size out of SSV,
701 * because Staffscale won't be
703 MALLOCA(char, label
, strlen(lab_p
->label
) + 1);
704 memcpy(label
, lab_p
->label
,
705 strlen(lab_p
->label
) + 1);
707 svpath(Labellist
[li
].staffno
,
708 STAFFSCALE
)->staffscale
,
712 label
= lab_p
->label
;
715 x
= lab_p
->west
+ adj
;
716 /* Move above any other inner labels.
717 * The very inner-most stays centered on the
718 * staff, so ones above that have to be adjusted
719 * by its ascent. This label itself has to
720 * have enough room for half its height,
721 * since it was originally centered,
722 * for any between there, we need to skip
723 * past their entire height.
725 for (y_adjust
= 0.0, l_p
= lab_p
->next
;
726 l_p
!= 0; l_p
= l_p
->next
) {
727 if (l_p
->next
== 0) {
728 y_adjust
+= strascent(
729 l_p
->label
) + STDPAD
;
732 y_adjust
+= strheight(
733 l_p
->label
) + STDPAD
;
736 if (lab_p
->next
!= 0) {
737 y_adjust
+= strheight(lab_p
->label
)
740 y
= Staffs_y
[ Labellist
[li
].staffno
]
741 + (strheight(label
) / 2.0)
744 pr_string(x
, y
, label
, J_CENTER
, (char *) 0, -1);
745 if (lab_p
->is_staff_label
== YES
) {
750 /* do labels that fall between staffs */
751 for (lab_p
= Labellist
[li
].btwnlabel_p
;
752 lab_p
!= (struct LABELINFO
*) 0;
753 lab_p
= lab_p
->next
) {
754 label
= lab_p
->label
;
755 x
= lab_p
->west
+ adj
;
756 /* y is the midpoint between the staffs,
757 * adjusted by the height/ascent of the label,
758 * and for any other labels. */
759 for (y_adjust
= 0.0, l_p
= lab_p
->next
;
760 l_p
!= 0; l_p
= l_p
->next
) {
761 if (l_p
->next
== 0) {
762 y_adjust
+= strascent(
763 l_p
->label
) + STDPAD
;
766 y_adjust
+= strheight(
767 l_p
->label
) + STDPAD
;
770 if (lab_p
->next
!= 0) {
771 y_adjust
+= strheight(lab_p
->label
)
774 y
= (Staffs_y
[ Labellist
[li
].staffno
] +
775 Staffs_y
[ Labellist
[li
+1].staffno
])/2.0
776 + (strheight(label
) / 2.0)
777 - strascent(label
) + y_adjust
;
778 pr_string(x
, y
, label
, J_CENTER
, (char *) 0, -1);
783 adj
= - (Maxlevels
* 2.0 * STDPAD
);
786 /* print the braces and brackets themselves */
787 for (s
= 1; s
<= Score
.staffs
; s
++) {
788 for (brac_p
= Brac_info_p
[s
]; brac_p
!= (struct BRAC_INFO
*) 0;
789 brac_p
= brac_p
->nested_p
) {
790 x
= x_offset
+ adj
+ (Maxlevels
- brac_p
->nestlevel
+ 1)
791 * (2.0 * STDPAD
) + (2.0 * STEPSIZE
)
792 + Nested_brace_adjust
;
793 if (brac_p
->bractype
== BRACELIST
) {
794 if (brac_p
->nested_by_p
== 0) {
795 x
+= (0.5 * STEPSIZE
);
798 x
-= (0.5 * STEPSIZE
);
801 if (brac_p
->topvisstaff
> 0) {
802 /* figure out y (the top). Start at the y
803 * of the top staff, then adjust as needed. */
804 y
= Staffs_y
[brac_p
->topvisstaff
];
806 /* figure out how tall the staff is effectively.
807 * Staffs with only a few stafflines are
808 * effectively taller than the number of
810 if ((eff_stafflines
= svpath(
811 brac_p
->topvisstaff
, STAFFLINES
) ->stafflines
) < 3) {
814 /* stepsizes are taller on tab staffs */
815 tab_adjust
= (is_tab_staff(brac_p
->topvisstaff
)
818 /* adjust for height of staff */
819 eff_stepsize
= svpath(brac_p
->topvisstaff
,
820 STAFFSCALE
)->staffscale
822 y
+= (eff_stafflines
- 1) * eff_stepsize
825 /* nested brackets should be a little shorter
826 * vertically to fit inside their parent.
827 * But beyond about 4 levels, if there is
828 * only a single staff, things look
829 * pretty bad, so limit to 4. */
830 y
-= (eff_stepsize
* (brac_p
->nestlevel
< 5
831 ? brac_p
->nestlevel
: 4));
833 /* brackets are 1 stepsize taller than braces */
834 if (brac_p
->bractype
== BRACKLIST
) {
838 /* now calculate y1 (the bottom) by similar
840 y1
= Staffs_y
[brac_p
->botvisstaff
];
842 /* figure out how tall the staff is effectively.
843 * Staffs with only a few stafflines are
844 * effectively taller than the number of
846 if ((eff_stafflines
= svpath(
847 brac_p
->botvisstaff
, STAFFLINES
) ->stafflines
) < 3) {
850 /* stepsizes are taller on tab staffs */
851 tab_adjust
= (is_tab_staff(brac_p
->botvisstaff
)
854 /* adjust for height of staff */
855 eff_stepsize
= svpath(brac_p
->botvisstaff
,
856 STAFFSCALE
)->staffscale
858 y1
-= (eff_stafflines
- 1) * eff_stepsize
861 /* nested brackets should be a little shorter
862 * vertically to fit inside their parent.
863 * But beyond about 4 levels, if there is
864 * only a single staff, things look
865 * pretty bad, so limit to 4. */
866 y1
+= (eff_stepsize
* (brac_p
->nestlevel
< 5
867 ? brac_p
->nestlevel
: 4));
869 /* brackets are 1 stepsize taller than braces */
870 if (brac_p
->bractype
== BRACKLIST
) {
874 /* now do the actual printing */
875 do_pr_brac(x
, y
, y1
, brac_p
->bractype
);
881 return(printed_brac
);
885 /* Given one MAINLL pointing to a FEED, find the previous one.
886 * Many functions in this file need the previous feed. At abshorz time,
887 * there may not be an actual FEED yet, it might just be proposed,
888 * so functions at that time need to provide that proposed FEED place.
889 * Once all the FEEDs are determined, we can use this function to
890 * find the previous one.
893 static struct MAINLL
*
894 find_prev_feed_mll_p(mll_p
)
896 struct MAINLL
*mll_p
;
899 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
900 if (IS_CLEFSIG_FEED(mll_p
)) {
908 /* Determine which label to use for a given staff.
909 * Goes backwards from mll_p, finding if label has been changed more recently
910 * than the previous feed. If so, use that label, else use label2.
914 label4staff(mll_p
, s
, prev_feed_mll_p
)
916 struct MAINLL
*mll_p
; /* should point to an actual or proposed FEED location */
918 struct MAINLL
*prev_feed_mll_p
; /* should point to an actual or proposed FEED location */
921 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
922 if (mll_p
== prev_feed_mll_p
) {
925 if (mll_p
->str
== S_SSV
) {
926 struct SSV
*ssv_p
= mll_p
->u
.ssv_p
;
928 /* If user changed label for this staff in staff
929 * context more recently that the previous feed,
930 * then that's the label we need. */
931 if (ssv_p
->context
== C_STAFF
&& ssv_p
->staffno
== s
932 && ssv_p
->used
[LABEL
] == YES
) {
933 return(ssv_p
->label
);
936 /* If user changed the score-wide label
937 * more recently than the previous feed,
938 * but there isn't any label set in staff context for
939 * this staff to override the score level label,
940 * then the score level label is the one we need. */
941 if (ssv_p
->context
== C_SCORE
&&
942 ssv_p
->used
[LABEL
] == YES
&&
943 Staff
[s
-1].used
[LABEL
] == NO
) {
944 return(ssv_p
->label
);
949 /* Hit another feed before any relevent label changes,
950 * so we need to use label2 */
951 return(svpath(s
, LABEL2
)->label2
);
953 /* Ran off the top of the song. Use label */
954 return(svpath(s
, LABEL
)->label
);
958 /* Given information about a set of grouped staffs,
959 * return the appropriate label to use: label or label2.
963 label4group(mll_p
, brac_p
, prev_feed_mll_p
)
965 struct MAINLL
*mll_p
;
966 struct BRAC_INFO
*brac_p
;
967 struct MAINLL
*prev_feed_mll_p
;
970 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
971 if (mll_p
== prev_feed_mll_p
) {
972 /* Hasn't changed since previous feed, so label2 */
973 return(brac_p
->staffset_p
->label2
);
975 if (mll_p
->str
== S_SSV
&& mll_p
->u
.ssv_p
->context
== C_SCORE
&&
976 mll_p
->u
.ssv_p
->used
[brac_p
->bractype
] == YES
) {
977 /* found SSV where brace/bracket was changed */
981 /* Either changed since previous feed or is the first feed in song,
983 return(brac_p
->staffset_p
->label
);
987 /* Return width of default label if the default label is needed (for
988 * indent of first score. Returns 0.0 if default label should not be used.
992 dflt_label_width(mll_p
, prev_feed_mll_p
)
994 struct MAINLL
*mll_p
; /* points to FEED or proposed place
995 * where current FEED will be */
996 struct MAINLL
*prev_feed_mll_p
; /* points to previous FEED, or proposed
997 * place where prev FEED will be */
1003 for (mll_p
= mll_p
->prev
; mll_p
!= 0; mll_p
= mll_p
->prev
) {
1004 if (mll_p
== prev_feed_mll_p
) {
1005 /* not the first; so don't use default for first */
1009 if (mll_p
->str
== S_SSV
&& mll_p
->u
.ssv_p
->context
== C_SCORE
&&
1010 mll_p
->u
.ssv_p
->used
[LABEL
] == YES
) {
1011 /* explicit label for first, so don't use default */
1015 (void) sprintf(dfltlabel
, "%c%c ", FONT_TR
, DFLT_SIZE
);
1016 return(strwidth(dfltlabel
));