Use scalar instead of embedded_scm for context mod overrides.
[lilypond/mpolesky.git] / lily / extender-engraver.cc
bloba46489be399ccf6f710a2e68b4e8652478894996
1 /*
2 extender-engraver.cc -- implement Extender_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2009 Glen Prideaux <glenprideaux@iname.com>,
7 Han-Wen Nienhuys <hanwen@xs4all.nl>,
8 Jan Nieuwenhuizen <janneke@gnu.org>
9 */
10 #include "context.hh"
11 #include "engraver.hh"
12 #include "international.hh"
13 #include "item.hh"
14 #include "lyric-extender.hh"
15 #include "note-head.hh"
16 #include "pointer-group-interface.hh"
17 #include "stream-event.hh"
18 #include "warn.hh"
19 #include "spanner.hh"
20 #include "paper-column.hh"
22 #include "translator.icc"
24 void completize_extender (Spanner *sp);
26 class Extender_engraver : public Engraver
28 Stream_event *ev_;
29 Spanner *extender_;
30 Spanner *pending_extender_;
31 bool current_lyric_is_skip_;
33 public:
34 TRANSLATOR_DECLARATIONS (Extender_engraver);
36 protected:
37 DECLARE_TRANSLATOR_LISTENER (extender);
38 DECLARE_ACKNOWLEDGER (lyric_syllable);
40 virtual void finalize ();
42 void stop_translation_timestep ();
43 void process_music ();
46 Extender_engraver::Extender_engraver ()
48 current_lyric_is_skip_ = false;
49 extender_ = 0;
50 pending_extender_ = 0;
51 ev_ = 0;
54 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
55 void
56 Extender_engraver::listen_extender (Stream_event *ev)
58 ASSIGN_EVENT_ONCE (ev_, ev);
61 void
62 Extender_engraver::process_music ()
64 if (ev_)
65 extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
68 void
69 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
71 Item *item = i.item ();
72 if (extender_)
73 extender_->set_bound (LEFT, item);
75 SCM text = item->get_property ("text");
76 current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
78 if (pending_extender_ && !current_lyric_is_skip_)
80 pending_extender_->set_object ("next", item->self_scm ());
81 completize_extender (pending_extender_);
82 pending_extender_ = 0;
86 void
87 Extender_engraver::stop_translation_timestep ()
89 if (extender_ || pending_extender_)
91 Context *voice = get_voice_to_lyrics (context ());
92 Grob *h = voice ? get_current_note_head (voice) : 0;
94 if (h)
96 if (extender_)
98 Pointer_group_interface::add_grob (extender_,
99 ly_symbol2scm ("heads"), h);
102 if (pending_extender_)
104 Pointer_group_interface::add_grob (pending_extender_,
105 ly_symbol2scm ("heads"), h);
107 The following check addresses the case where the lyrics end before
108 the associated voice. The current_lyric_is_skip_ check is
109 necessary to handle manual melismata, which should not result in
110 extenders being completized. We also need to make sure that we're not
111 in the middle of a note (happens when this function is called because
112 of an event in a voice other than our associated one).
114 if (!melisma_busy (voice) && !current_lyric_is_skip_)
116 Moment now = voice->now_mom ();
117 Paper_column *column = (dynamic_cast<Item *> (h))->get_column ();
118 Moment *start_mom = column ? unsmob_moment (column->get_property ("when")) : 0;
119 if (!column || (start_mom->main_part_ == now.main_part_))
121 completize_extender (pending_extender_);
122 pending_extender_ = 0;
127 else
129 if (pending_extender_
130 && !get_property ("extendersOverRests"))
132 completize_extender (pending_extender_);
133 pending_extender_ = 0;
137 if (extender_)
139 pending_extender_ = extender_;
140 extender_ = 0;
144 ev_ = 0;
147 void
148 completize_extender (Spanner *sp)
150 if (!sp->get_bound (RIGHT))
152 extract_item_set (sp, "heads", heads);
153 if (heads.size ())
154 sp->set_bound (RIGHT, heads.back ());
158 void
159 Extender_engraver::finalize ()
161 if (extender_)
163 completize_extender (extender_);
165 if (!extender_->get_bound (RIGHT))
166 extender_->warning (_ ("unterminated extender"));
167 extender_ = 0;
170 if (pending_extender_)
172 completize_extender (pending_extender_);
174 if (!pending_extender_->get_bound (RIGHT))
175 pending_extender_->warning (_ ("unterminated extender"));
176 pending_extender_ = 0;
180 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
181 ADD_TRANSLATOR (Extender_engraver,
182 /* doc */
183 "Create lyric extenders.",
185 /* create */
186 "LyricExtender ",
188 /* read */
189 "extendersOverRests ",
191 /* write */