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));