1 /* Copyright (c) 1997, 1998, 1999, 2001, 2003, 2004 by Arkkra Enterprises */
2 /* All rights reserved. */
4 /* functions to support printing of tab staffs */
10 /* position of the last bend arrow for each staff, or 0.0 if no
11 * arrow on previous group */
12 static double Last_x_arrow
[MAXSTAFFS
+ 1], Last_y_arrow
[MAXSTAFFS
+ 1];
14 static double pr_tab_note
P((int note_index
, struct GRPSYL
*gs_p
,
15 double y_adjust
, struct MAINLL
*mll_p
));
16 static double pr_bstring
P((struct GRPSYL
*gs_p
, struct NOTE
*note_p
,
17 int note_index
, double y_adjust
, struct MAINLL
*mll_p
));
18 static void pr_b_arrow
P((struct GRPSYL
*gs_p
, struct MAINLL
*mll_p
,
20 static void pr_b_curve
P((float *xlist
, float *ylist
, struct GRPSYL
*gs_p
,
22 static void pr_arrowhead
P((struct GRPSYL
*gs_p
, double y_adjust
, int headchar
));
23 static int bends_up
P((struct GRPSYL
*gs_p
, int n
, struct GRPSYL
*pgs_p
,
25 static int is_carried_in_bend
P((struct MAINLL
*mll_p
,
26 struct MAINLL
*prev_mll_p
));
30 /* given a GRPSYL list for a tab staff, print all the notes in the list */
33 pr_tab_groups(gs_p
, mll_p
)
40 double y_adjust
; /* to account for bend string space */
41 struct GRPSYL
*ngs_p
; /* next group */
45 /* go through the list of groups */
46 for ( ; gs_p
!= (struct GRPSYL
*) 0; gs_p
= gs_p
->next
) {
48 /* if inhibitprint flag is set (because this is a tied-to
49 * group), skip this group */
50 if (gs_p
->inhibitprint
== YES
) {
54 /* measure repeats are special */
55 if (is_mrpt(gs_p
) == YES
) {
56 pr_mrpt(gs_p
, mll_p
->u
.staff_p
);
60 /* multirests are special. Print on tab staff only if its
61 * corresponding tabnote staff is not printed */
62 if (gs_p
->basictime
< -1) {
63 if (svpath(gs_p
->staffno
- 1, VISIBLE
)->visible
== NO
) {
64 pr_multirest(gs_p
, mll_p
->u
.staff_p
);
69 /* print the fret number and bend string
70 * for each note in the group. The
71 * y_adjust gets changed to account for space taken up
72 * by bend text strings */
74 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
75 y_adjust
= pr_tab_note(n
, gs_p
, y_adjust
, mll_p
);
78 /* if there were any bends, draw the arrow. Otherwise
79 * remember that there are no bends in progress */
81 pr_b_arrow(gs_p
, mll_p
, y_adjust
);
84 Last_y_arrow
[gs_p
->staffno
] = 0.0;
85 Last_x_arrow
[gs_p
->staffno
] = 0.0;
88 /* print any slashes */
89 if (gs_p
->slash_alt
> 0) {
90 /* slashes on tab staff get hard-coded
91 * tilt value of 2.2 * Stdpad. */
92 if (gs_p
->stemdir
== UP
) {
93 pr_slashes(gs_p
, (double) gs_p
->c
[AX
],
94 (double) (gs_p
->notelist
[gs_p
->nnotes
- 1].c
[AY
]
95 + gs_p
->stemlen
), (double) -1.0,
96 (double) 0.0, (double) (2.2 * Stdpad
));
99 pr_slashes(gs_p
, (double) gs_p
->c
[AX
],
100 (double) (gs_p
->notelist
[0].c
[AY
]
101 - gs_p
->stemlen
), (double) 1.0,
102 (double) 0.0, (double) (2.2 * Stdpad
));
106 if (gets_roll(gs_p
, mll_p
->u
.staff_p
, 0) == YES
) {
110 /* print any "with" list items */
113 /* on last group in measure, have to look ahead to next group
114 * if any to see if it has a bend from this note and is on
115 * the next score. If so, have to draw a horizontal line for
116 * the bend out to near the end of the current score */
117 if (gs_p
->next
== (struct GRPSYL
*) 0) {
118 /* is the last group in the measure. See if we are
119 * at a scorefeed. First search for end of current
121 for (m_p
= mll_p
; m_p
!= (struct MAINLL
*) 0 &&
122 m_p
->str
!= S_BAR
; m_p
= m_p
->next
) {
126 /* now go until we find either a feed or a staff */
127 for ( ; m_p
!= (struct MAINLL
*) 0;
129 if (m_p
->str
== S_FEED
|| m_p
->str
== S_STAFF
) {
133 if (m_p
== (struct MAINLL
*) 0 || m_p
->str
!= S_FEED
) {
134 /* no next group or not at a scorefeed */
138 /* See if there is another group in the next measure */
139 if ((ngs_p
= nextgrpsyl(gs_p
, &mll_p
))
140 == (struct GRPSYL
*) 0) {
144 if (ngs_p
->nnotes
== 0) {
148 for (n
= 0; n
< ngs_p
->nnotes
; n
++) {
149 if (HASREALBEND(ngs_p
->notelist
[n
]) &&
150 ngs_p
->notelist
[n
].FRETNO
== NOFRET
) {
151 /* next group has a real, non-prebend
152 * bend, so have to deal with it */
155 else if (HASNULLBEND(ngs_p
->notelist
[n
])) {
156 /* has null bend. have to do this one */
160 if (n
== ngs_p
->nnotes
) {
161 /* no non-prebend bend */
165 /* if we got here, this is the special case where we
166 * do need to draw the line, so do it */
167 do_linetype(L_NORMAL
);
168 if (Last_y_arrow
[gs_p
->staffno
] != 0.0) {
169 draw_line( (double) (Last_x_arrow
[gs_p
->staffno
]),
170 (double) (Last_y_arrow
[gs_p
->staffno
]),
172 - eff_rightmargin(mll_p
) - Stepsize
),
173 (double) (Last_y_arrow
[gs_p
->staffno
]));
174 Last_x_arrow
[gs_p
->staffno
] =
175 PGWIDTH
- eff_rightmargin(mll_p
)
179 /* the bend is on the next score, but not a
180 * continuation bend. so draw an arrow towards
181 * the margin, followed by a short
183 float xlist
[6], ylist
[6]; /* curve coords */
184 struct GRPSYL dummy_gs
; /* for curve end */
187 /* set place for beginning of curve */
188 xlist
[0] = gs_p
->notelist
[n
].c
[AX
] + Stdpad
+
189 notehorz(gs_p
, &(gs_p
->notelist
[n
]), RE
);
190 ylist
[0] = gs_p
->notelist
[n
].c
[AY
];
192 /* fill in a dummy GRPSYL struct with just
193 * the pieces of information that pr_b_curve
194 * will need to draw a bend curve */
195 dummy_gs
.c
[AX
] = PGWIDTH
196 - eff_rightmargin(mll_p
)
198 dummy_gs
.c
[AN
] = ylist
[0] + 2.4 * Stepsize
200 /* if we're too close to the margin, make the
201 * curve a little longer, so it will look
202 * decent, even if it runs into the margin
204 if (dummy_gs
.c
[AX
] - xlist
[0]
206 dummy_gs
.c
[AX
] = 3.0 * Stepsize
;
207 /* If that still didn't move it enough
208 * to avoid having the bend backwards,
209 * adjust some more */
210 if (dummy_gs
.c
[AX
] - xlist
[0]
212 dummy_gs
.c
[AX
] = xlist
[0]
218 pr_b_curve(xlist
, ylist
, &dummy_gs
, 0.0);
220 /* draw an arrow at the end of the curve */
221 pr_muschar( (double) dummy_gs
.c
[AX
],
222 (double) (dummy_gs
.c
[AN
] -
223 (height(FONT_MUSIC
, DFLT_SIZE
, C_UWEDGE
)
224 / 2.0)), C_UWEDGE
, DFLT_SIZE
, FONT_MUSIC
);
226 /* draw a short dashed line to the right
227 * from the arrow, to indicate the actual
228 * bend is on the next score */
229 do_linetype(L_DASHED
);
230 ylist
[5] += 2.0 * Stdpad
;
231 draw_line( (double) xlist
[5] + Stdpad
,
233 (double) xlist
[5] + 3.5 * Stepsize
,
241 /* print things for a tab staff note. Return any adjustment to North needed
242 * to account for bend string */
245 pr_tab_note(note_index
, gs_p
, y_adjust
, mll_p
)
247 int note_index
; /* which note in gs_p */
249 double y_adjust
; /* to account for bend string space */
250 struct MAINLL
*mll_p
; /* main list struct pointing to gs_p */
254 char *fretstr
; /* text string to print for fret number */
256 note_p
= &(gs_p
->notelist
[note_index
]);
258 /* print fret number (with parentheses if appropriate) */
259 fretstr
= fret_string(note_p
, gs_p
);
260 if ( *fretstr
!= '\0') {
262 if (vvpath(gs_p
->staffno
, gs_p
->vno
, TABWHITEBOX
)->tabwhitebox
== YES
) {
263 /* Put a white box behind the number, so the line
264 * doesn't go through it, making it easier to read. */
265 do_whitebox( note_p
->c
[AX
] - strwidth(fretstr
) / 2.0,
266 note_p
->c
[AY
] - strheight(fretstr
) / 2.0,
267 note_p
->c
[AX
] + strwidth(fretstr
) / 2.0,
268 note_p
->c
[AY
] + strheight(fretstr
) / 2.0);
271 pr_string( (double) (note_p
->c
[AX
] - (strwidth(fretstr
) / 2.0)),
272 (double) (note_p
->c
[AY
] + (strheight(fretstr
) / 2.0)
273 - strascent(fretstr
)),
274 fretstr
, J_LEFT
, gs_p
->inputfile
, gs_p
->inputlineno
);
277 /* print a bend string if appropriate */
278 if ( HASBEND((*note_p
)) ) {
279 if (HASREALBEND(*note_p
)) {
280 y_adjust
+= pr_bstring(gs_p
, note_p
, note_index
,
284 /* need to return a little bit, so later code
285 * knows that there was a bend of some sort */
286 if (y_adjust
== 0.0) {
295 /* print the bend string ("full", "1/2", etc). Return its height */
298 pr_bstring(gs_p
, note_p
, note_index
, y_adjust
, mll_p
)
300 struct GRPSYL
*gs_p
; /* group having a bend */
301 struct NOTE
*note_p
; /* which note in gs_p has the bend */
302 int note_index
; /* index into gs_p->notelist of note_p */
303 double y_adjust
; /* to account for bend strings done previously
304 * for this group (on other notes in the group */
305 struct MAINLL
*mll_p
; /* main list struct pointing to gs_p */
309 double x_adjust
; /* to center upward and left justify
310 * downward, to not collide with curve */
311 struct GRPSYL
*pgs_p
; /* previous group */
312 int n
; /* index through notelist */
315 /* get what to print for the bend */
316 bstring
= bend_string(note_p
);
318 /* generally, the string should be centered. */
319 x_adjust
= strwidth(bstring
) / 2.0;
321 /* However, if not a prebend and the bend is downward,
322 * then we have to move the bend string over so it
323 * doesn't collide with the curve. So first get the previous group
324 * and see it is has a bend too. If it does, see if the bend is
325 * downward, and if so, change to left justify rather than center */
326 if (note_p
->FRETNO
== NOFRET
&& (pgs_p
= prevgrpsyl(gs_p
, &mll_p
))
327 != (struct GRPSYL
*) 0) {
329 for (n
= 0; n
< pgs_p
->nnotes
; n
++) {
330 if (pgs_p
->notelist
[n
].STRINGNO
331 == gs_p
->notelist
[note_index
].STRINGNO
332 && HASBEND(pgs_p
->notelist
[n
])) {
333 if (bends_up(gs_p
, note_index
, pgs_p
, NO
) == NO
) {
340 /* print the bend string */
341 pr_string( (double) (gs_p
->c
[AX
] - x_adjust
),
342 (double) (gs_p
->c
[AN
] - strascent(bstring
) - y_adjust
),
343 bstring
, J_LEFT
, gs_p
->inputfile
, gs_p
->inputlineno
);
345 /* return the height of what was just printed */
346 return(strheight(bstring
));
350 /* print bend arrow */
353 pr_b_arrow(gs_p
, mll_p
, y_adjust
)
356 struct MAINLL
*mll_p
;
360 struct GRPSYL
*pgs_p
; /* previous grpsyl */
361 struct MAINLL
*prev_mll_p
; /* where pgs_p is connected */
362 float xlist
[6], ylist
[6]; /* coords of bend curve */
363 int n
; /* note index */
365 int carried_in
; /* YES if bend is carried in */
368 staffno
= gs_p
->staffno
;
370 /* leave a little room between bend string and the arrow. This is
371 * especially needed when bending down, so the string and curve
373 y_adjust
+= 2.0 * Stdpad
;
375 /* find the first note with a bend on it */
376 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
377 if (HASBEND(gs_p
->notelist
[n
])) {
382 /* the function isn't supposed to get called unless there really
383 * is a bend somewhere on the group */
384 if (n
== gs_p
->nnotes
) {
385 pfatal("pr_b_arrow couldn't find note with bend");
388 /* check if prebend or non-prebend */
389 if (gs_p
->notelist
[n
].FRETNO
!= NOFRET
390 && ! HASNULLBEND(gs_p
->notelist
[n
])) {
391 /* this is a prebend */
392 /* draw the line straight up from the fret number */
393 do_linetype(L_NORMAL
);
394 draw_line( (double) (gs_p
->c
[AX
]),
395 (double) (gs_p
->notelist
[n
].c
[AN
] + Stdpad
),
396 (double) (gs_p
->c
[AX
]),
397 (double) (gs_p
->c
[AN
] - y_adjust
));
399 /* draw triangle at top */
400 pr_arrowhead(gs_p
, y_adjust
, C_UWEDGE
);
404 /* a normal bend, not a prebend */
406 if ((pgs_p
= prevgrpsyl(gs_p
, &prev_mll_p
)) == (struct GRPSYL
*) 0) {
407 l_ufatal(gs_p
->inputfile
, gs_p
->inputlineno
,
408 "no previous chord for bend");
411 carried_in
= is_carried_in_bend(mll_p
, prev_mll_p
);
413 if (Last_y_arrow
[staffno
] == 0.0) {
414 /* not the continuation of an in-progress bend */
416 /* do each note that has a bend */
417 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
418 if ( ! HASBEND(gs_p
->notelist
[n
])) {
422 if ((mll_p
!= prev_mll_p
&& pgs_p
->c
[AE
] > gs_p
->c
[AX
])
423 || carried_in
== YES
) {
425 /* either an intervening scorefeed or
426 * carried in to subsequent ending,
427 * so just start a bit west
428 * of the current group */
429 xlist
[0] = gs_p
->c
[AW
] - 2.0 * Stepsize
;
430 ylist
[0] = gs_p
->c
[AY
] +
431 gs_p
->notelist
[n
].stepsup
432 * Stepsize
* TABRATIO
;
435 /* beginning of bend arrow is at east
437 * above the center of the fret number
438 * of the previous group */
439 xlist
[0] = pgs_p
->c
[AE
] + Stdpad
;
440 ylist
[0] = gs_p
->notelist
[n
].c
[AY
] + Stdpad
;
443 pr_b_curve(xlist
, ylist
, gs_p
, y_adjust
);
445 pr_arrowhead(gs_p
, y_adjust
, C_UWEDGE
);
448 /* continuation of an in-progress bend */
450 /* find the note that has a bend. Only allowed to be
451 * one note with a continuation bend, or could be a release,
452 * in which case we use the first note we find */
453 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
454 if ( HASBEND(gs_p
->notelist
[n
])) {
458 if (n
== gs_p
->nnotes
) {
459 pfatal("unable to find note with continuation bend");
462 /* find the starting point of the bend curve */
463 if ((mll_p
!= prev_mll_p
&& pgs_p
->c
[AE
] > gs_p
->c
[AX
])
464 || carried_in
== YES
) {
466 /* must have been an intervening scorefeed,
467 * so just start a bit west
468 * of the current group */
469 xlist
[0] = gs_p
->c
[AW
] - 2.0 * Stepsize
;
470 Last_y_arrow
[staffno
] = gs_p
->c
[AN
] - y_adjust
;
472 /* need to adjust more if bending is actually up */
473 if (bends_up(gs_p
, n
, pgs_p
, carried_in
)) {
474 Last_y_arrow
[staffno
] -= 3.0 * Stepsize
;
477 /* null bends carried over a scorefeed
478 * have to be done specially */
479 if (HASNULLBEND(gs_p
->notelist
[n
])) {
480 Last_y_arrow
[staffno
] = gs_p
->notelist
[n
].c
[AN
]
481 + (2 * gs_p
->notelist
[n
].STRINGNO
482 * Stepsize
* TABRATIO
);
483 if (gs_p
->notelist
[n
].STRINGNO
== 0) {
484 Last_y_arrow
[staffno
] += 2.0 * Stepsize
490 /* beginning of bend curve is where last
492 xlist
[0] = Last_x_arrow
[staffno
];
494 ylist
[0] = Last_y_arrow
[staffno
];
496 /* determine whether curve goes up or down
497 * and find its endpoint */
498 if (bends_up(gs_p
, n
, pgs_p
, carried_in
) == YES
) {
499 /* bending up some more */
500 pr_b_curve(xlist
, ylist
, gs_p
, y_adjust
);
501 pr_arrowhead(gs_p
, y_adjust
, C_UWEDGE
);
503 else { /* bending back downwards */
505 if ( ! HASREALBEND(gs_p
->notelist
[n
])) {
506 /* null bend. Have to draw curve all the way
507 * down to the appropriate "note" */
508 y_adjust
= gs_p
->c
[AN
] -
509 gs_p
->notelist
[n
].c
[AN
] - Stdpad
-
510 height(FONT_MUSIC
, DFLT_SIZE
, C_WEDGE
)
513 pr_b_curve(xlist
, ylist
, gs_p
, y_adjust
);
514 pr_arrowhead(gs_p
, y_adjust
, C_WEDGE
);
520 /* given the first point of a bend curve, plus the gs_p and y adjustment for
521 * the end of the curve, figure out the points of the curve and draw it */
524 pr_b_curve(xlist
, ylist
, gs_p
, y_adjust
)
526 float *xlist
; /* arrays of x & y coordinates, with 6 members */
529 double y_adjust
; /* how far from the north of the gs_p the curve is */
535 /* last point of bend arrow is just below
537 xlist
[5] = gs_p
->c
[AX
];
538 ylist
[5] = gs_p
->c
[AN
] - y_adjust
- Stdpad
;
540 /* fill in intermediate points */
541 xlen
= xlist
[5] - xlist
[0];
542 ylen
= ylist
[5] - ylist
[0];
543 xlist
[1] = xlist
[0] + xlen
* 0.15;
545 xlist
[2] = xlist
[0] + xlen
* 0.7;
546 ylist
[2] = ylist
[0] + ylen
* 0.2;
547 xlist
[3] = xlist
[5] - xlen
* 0.2;
548 ylist
[3] = ylist
[5] - ylen
* 0.7;
550 ylist
[4] = ylist
[5] - ylen
* 0.15;
553 do_linetype(L_NORMAL
);
554 pr_allcurve(xlist
, ylist
, 6, W_NORMAL
, NO
);
558 /* print arrowhead at the end of a bend curve */
561 pr_arrowhead(gs_p
, y_adjust
, headchar
)
565 int headchar
; /* C_WEDGE or C_UWEDGE */
568 pr_muschar( (double) gs_p
->c
[AX
],
569 (double) (gs_p
->c
[AN
] - y_adjust
-
570 (height(FONT_MUSIC
, DFLT_SIZE
, headchar
) / 2.0)),
571 headchar
, DFLT_SIZE
, FONT_MUSIC
);
573 Last_y_arrow
[gs_p
->staffno
] = gs_p
->c
[AN
] - y_adjust
;
574 Last_x_arrow
[gs_p
->staffno
] = gs_p
->c
[AX
];
578 /* given a GRPSYL that has a continuation bend, or is a carried-in bend,
579 * return YES if it is bending
580 * upwards from the previous bend, NO if not */
583 bends_up(gs_p
, n
, pgs_p
, carried_in
)
585 struct GRPSYL
*gs_p
; /* group having a continuation bend */
586 int n
; /* the note index in gs_p having the bend */
587 struct GRPSYL
*pgs_p
; /* previous group */
588 int carried_in
; /* YES if bend is carried in */
591 RATIONAL thisgrp_bend
; /* rational version of bend on this group */
592 RATIONAL prevgrp_bend
; /* rational version of bend on previous group */
593 int i
; /* index through pgs_p notes */
596 if (gs_p
== (struct GRPSYL
*) 0 || pgs_p
== (struct GRPSYL
*) 0) {
597 pfatal("null pointer passed to bends_up");
600 /* get rational version of the bend distance on continuation note */
601 thisgrp_bend
= ratbend( &(gs_p
->notelist
[n
]) );
603 /* find the corresponding note in the previous group */
604 for (i
= 0; i
< pgs_p
->nnotes
; i
++) {
605 if (pgs_p
->notelist
[i
].STRINGNO
== gs_p
->notelist
[n
].STRINGNO
) {
609 if (i
== pgs_p
->nnotes
) {
610 pfatal("couldn't find the note being bent from");
613 /* get rational version of that bend */
614 if ( ! HASBEND(pgs_p
->notelist
[i
]) ) {
615 /* if this is a carried-in bend, it may not be a continuation
616 * bend, but in that case, it has to be bending up */
617 if (carried_in
== YES
) {
621 l_ufatal(gs_p
->inputfile
, gs_p
->inputlineno
,
622 HASNULLBEND(gs_p
->notelist
[n
]) ?
623 "bend release not preceded by a bend" :
624 "no bend on note supposedly being bent from");
627 prevgrp_bend
= ratbend( &(pgs_p
->notelist
[i
]) );
629 /* compare the bends */
630 if (GT(thisgrp_bend
, prevgrp_bend
)) {
633 else if (LT(thisgrp_bend
, prevgrp_bend
)) {
637 l_ufatal(gs_p
->inputfile
, gs_p
->inputlineno
,
638 "can't bend to the same distance as previous bend");
645 /* Return YES if the bend is carried in to a subsequent ending, NO if just
650 is_carried_in_bend(mll_p
, prev_mll_p
)
652 struct MAINLL
*mll_p
; /* where group with a bend is attached */
653 struct MAINLL
*prev_mll_p
; /* where the previous group is attached */
656 int num_startitems
; /* how many endingloc==STARTITEM were found */
659 /* if both groups are in the same measure, then it's definitely
660 * not a carried in bend */
661 if (mll_p
== prev_mll_p
) {
665 /* go forward from prev_mll_p until we get to mll_p. If we encounter
666 * more than 1 STARTITEM in endingloc, checking both normal and
667 * pseudo bars, then this was a carried in bend. */
669 for ( ; prev_mll_p
!= (struct MAINLL
*) 0 && prev_mll_p
!= mll_p
;
670 prev_mll_p
= prev_mll_p
->next
) {
672 switch (prev_mll_p
->str
) {
675 if (prev_mll_p
->u
.bar_p
->endingloc
== STARTITEM
) {
676 if (++num_startitems
> 1) {
677 /* it is carried in bend */
684 if (prev_mll_p
->u
.clefsig_p
->bar_p
!= (struct BAR
*) 0) {
685 if (prev_mll_p
->u
.clefsig_p
->bar_p
->endingloc
687 if (++num_startitems
> 1) {
695 /* nothing else is relevant at this point */
700 /* fell out without finding 2 STARTITEMS, so not carried in */
705 /* given internal representation of bend info,
706 * return string representation. Returns string in
707 * static area that is overwritten on each call.
716 static char buff
[12];
717 int intpart
, num
, den
;
719 /* separate internal representation into integer, numerator,
721 intpart
= BENDINT(*note_p
);
722 num
= BENDNUM(*note_p
);
723 den
= BENDDEN(*note_p
);
725 /* construct the string representation */
727 buff
[1] = adj_size(DFLT_SIZE
, Staffscale
, (char *) 0, -1);
729 if (intpart
== 1 && num
== 0) {
730 (void) strcpy(buff
+2, "full");
732 else if (intpart
== 0 && num
== 0) {
737 /* integer part only, no fraction */
738 (void) sprintf(buff
+2, "%d", intpart
);
740 else if (intpart
== 0) {
742 (void) sprintf(buff
+2, "%d/%d", num
, den
);
745 /* both integer and fractional parts */
746 (void) sprintf(buff
+2, "%d %d/%d", intpart
, num
, den
);
752 /* given a NOTE on a tab staff, return char * of what is to be printed
753 * for the fret number. Returned string is a static area
754 * that is overwritten on each call.
758 fret_string(note_p
, gs_p
)
761 struct GRPSYL
*gs_p
; /* group containing the note */
764 static char fretbuff
[8];
768 /* if no fret, return "" */
769 if (note_p
->FRETNO
== NOFRET
) {
774 size
= adj_size((note_p
->notesize
== GS_SMALL ? SMFRETSIZE
: DFLT_SIZE
),
775 Staffscale
, gs_p
->inputfile
, gs_p
->inputlineno
);
777 /* make proper string for X-note or normal fret number, in parentheses
779 if (IS_MUSIC_FONT(note_p
->headfont
)) {
780 (void) sprintf(fretbuff
,
781 (note_p
->FRET_HAS_PAREN ?
"%c%c(%c%c%c)" : "%c%c%c%c%c"),
782 FONT_HB
, size
, mfont2str(note_p
->headfont
),
783 size
, note_p
->headchar
);
786 (void) sprintf(fretbuff
,
787 (note_p
->FRET_HAS_PAREN ?
"%c%c(%d)" : "%c%c%d"),
788 FONT_HB
, size
, note_p
->FRETNO
);
794 /* print a TAB "clef" which is really just the word "TAB" written vertically.
795 * By convention, this only gets printed once per staff at the very beginning
796 * of the song. To keep things simple, the width of the clef is always
797 * returned as if the clef was printed even when it really isn't */
800 pr_tabclef(staffno
, x
, really_print
, size
)
808 static int did_tab_clef
[MAXSTAFFS
+ 1]; /* set to YES once we print a
809 * TAB clef on a given staff. Convention is to print
810 * this "clef" only at the very beginning of a song. */
812 int ptsize
; /* point size to use for "TAB" */
813 double width
, widest
; /* of the letters in "TAB" */
815 char letter
[4]; /* internal format version of one letter of "TAB" */
816 char *tabstr
; /* pointer through "TAB" */
820 /* adjust the size based on how many stafflines there are */
821 stafflines
= svpath(staffno
, STAFFLINES
)->stafflines
;
822 if (stafflines
< 4) {
825 else if (stafflines
== 4) {
828 else if (stafflines
== 5) {
835 /* if small clef, adjust the size (actually, this shouldn't
836 * ever happen unless we change some other things some day, but this
837 * way we will be prepared if/when that happens). */
838 if (size
!= DFLT_SIZE
) {
839 ptsize
= (int) (ptsize
* (size
/ DFLT_SIZE
));
841 ptsize
= adj_size(ptsize
, Staffscale
, (char *) 0, -1);
843 /* print/get width of "TAB" */
844 for (widest
= 0, tabstr
= "TAB"; *tabstr
!= '\0'; tabstr
++) {
846 /* create internal format string for current letter */
847 (void) sprintf(letter
, "%c%c%c", FONT_HB
, ptsize
, *tabstr
);
849 width
= strwidth(letter
);
851 /* save the widest letter width */
852 if (width
> widest
) {
856 /* if we're really supposed to print,
857 * print this letter of "TAB" */
858 if (really_print
== YES
&& did_tab_clef
[staffno
] == NO
) {
860 /* figure out where to place vertically */
861 if (*tabstr
== 'T') {
862 /* place the top letter */
863 height
= strheight(letter
);
864 y
= Staffs_y
[staffno
] + height
/ 2.0
868 /* move subsequent letters down by height
873 /* print the letter with a little space before */
874 pr_string(x
+ 3.0 * Stdpad
, y
, letter
, J_LEFT
,
879 /* only print once per staff */
880 if (really_print
== YES
) {
881 did_tab_clef
[staffno
] = YES
;
884 /* allow some space on either side */
885 return(widest
+ 6.0 * Stdpad
);