#include "engraver.hh"
+#include "music.hh"
#include "stream-event.hh"
+#include "international.hh"
#include "item.hh"
#include "pointer-group-interface.hh"
#include "spanner.hh"
void stop_translation_timestep ();
void finalize ();
+ virtual void derived_mark () const;
void footnotify (Grob *, Stream_event *);
};
void
Footnote_engraver::finalize ()
{
- annotated_spanners_.resize (0);
+ annotated_spanners_.clear ();
+}
+
+void
+Footnote_engraver::derived_mark () const
+{
+ for (vsize i = 0; i < events_.size (); ++i)
+ scm_gc_mark (events_[i]->self_scm ());
}
Footnote_engraver::Footnote_engraver ()
void
Footnote_engraver::acknowledge_grob (Grob_info info)
{
+ Music *mus = unsmob_music (info.grob ()->get_property ("footnote-music"));
+
+ if (mus)
+ {
+ if (!mus->is_mus_type ("footnote-event")) {
+ mus->origin ()->programming_error (_ ("Must be footnote-event."));
+ return;
+ }
+ Stream_event *ev = mus->to_event (context ());
+ footnotify (info.grob (), ev);
+ ev->unprotect ();
+ return;
+ }
+
+ // The following performance hog should eventually be removed:
+ // instead of adding a -\footnote ... \default articulation at the
+ // end of a note, you can perfectly well use \footnote ... before
+ // the note. This is just for the sake of automatic convert-ly
+ // rules.
+
Stream_event *cause = info.event_cause ();
SCM arts = cause ? cause->get_property ("articulations") : SCM_EOL;
footnotify (info.grob (), e);
}
+ // In contrast, the following code is only called when actual
+ // footnote events have been listened to. It should not affect
+ // performance.
+
for (vsize i = 0; i < events_.size (); i++)
{
if (info.grob ()->name () == ly_symbol2string (events_[i]->get_property ("symbol")))
"extra-X-extent "
"extra-Y-extent "
"extra-offset "
+ "footnote-music "
"forced-spacing "
"interfaces "
"layer "
argument))
footnote =
-#(define-music-function (parser location text offset grob-name footnote)
- ((markup?) number-pair? (symbol? '()) markup?)
- (_i "Attach @var{text} at @var{offset} with @var{text} referring to
-@var{footnote}. If @var{text} is given as @code{\\default}, use
-autonumbering instead. Note that, for this to take effect,
-auto-numbering must be turned on in the paper block. Otherwise, no
-number will appear. Footnotes are applied like articulations. If a
-symbol @var{grob-name} is specified, all grobs of that kind at the
-current time step are affected.")
- (make-music
- 'FootnoteEvent
- 'X-offset (car offset)
- 'Y-offset (cdr offset)
- 'automatically-numbered (not text)
- 'text (or text (make-null-markup))
- 'footnote-text footnote
- 'symbol grob-name))
+#(define-music-function (parser location mark offset grob-name footnote music)
+ ((markup?) number-pair? (symbol?) markup? (ly:music?))
+ (_i "Make the markup @var{footnote} a footnote on @var{music}. The
+footnote is marked with a markup @var{mark} moved by @var{offset} with
+respect to the marked music.
+
+If @var{mark} is not given or specified as @var{\\default}, it is
+replaced by an automatically generated sequence number. If a symbol
+@var{grob-name} is specified, then grobs of that type will be marked
+if they have @var{music} as their ultimate cause; by default all grobs
+having @var{music} as their @emph{direct} cause will be marked,
+similar to the way @code{\\tweak} works.
+
+If @var{music} is given as @code{\\default}, a footnote event
+affecting @emph{all} grobs matching @var{grob-name} at a given time
+step is generated. This may be required for creating footnotes on
+time signatures, clefs, and other items not cooperating with
+@code{\\tweak}.
+
+Like with @code{\\tweak}, if you use a footnote on a following
+post-event, the @code{\\footnote} command itself needs to be attached
+to the preceding note or rest as a post-event with @code{-}.")
+ (let ((mus (make-music
+ 'FootnoteEvent
+ 'X-offset (car offset)
+ 'Y-offset (cdr offset)
+ 'automatically-numbered (not mark)
+ 'text (or mark (make-null-markup))
+ 'footnote-text footnote
+ 'symbol (or grob-name '()))))
+ (if music
+ (begin
+ (set! (ly:music-property music 'tweaks)
+ (acons (if grob-name
+ (cons grob-name 'footnote-music)
+ 'footnote-music)
+ mus
+ (ly:music-property music 'tweaks)))
+ music)
+ mus)))
grace =
#(def-grace-function startGraceMusic stopGraceMusic
sub_tempo, str)
return str
+@rule((2, 15, 39), r"\footnote ... -> \footnote ... \default")
+def conv (str):
+ def not_first (s):
+ def match_fun (m):
+ if m.group (1):
+ return m.group (0)
+ return m.expand (s)
+ return match_fun
+ str = re.sub ("(" + matchmarkup + ")|"
+ + r"(\\footnote(?:\s*"
+ + matchmarkup + ")?" + matcharg + "(?:" + matcharg
+ + ")?\s+" + matchmarkup + ")",
+ not_first (r"\2 \\default"), str)
+ return str
# Guidelines to write rules (please keep this at the end of this file)
#
approximately 12% larger; 6@tie{}steps are exactly a factor@tie{}2
larger. Fractional values are allowed.")
(footnote ,boolean? "Should this be a footnote or in-note?")
+ (footnote-music ,ly:music? "Music creating a footnote.")
(footnote-text ,markup? "A footnote for the grob.")
(force-hshift ,number? "This specifies a manual shift for notes
in collisions. The unit is the note head width of the first voice