]> git.donarmstrong.com Git - lilypond.git/blob - lily/extender-engraver.cc
53938b24f6eee350da9b7995cf14ce3b85f715a5
[lilypond.git] / lily / extender-engraver.cc
1 /*
2   extender-engraver.cc -- implement Extender_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1999--2006 Glen Prideaux <glenprideaux@iname.com>,
7   Han-Wen Nienhuys <hanwen@xs4all.nl>,
8   Jan Nieuwenhuizen <janneke@gnu.org>
9 */
10
11 #include "context.hh"
12 #include "engraver.hh"
13 #include "international.hh"
14 #include "item.hh"
15 #include "lyric-extender.hh"
16 #include "note-head.hh"
17 #include "pointer-group-interface.hh"
18 #include "stream-event.hh"
19 #include "warn.hh"
20
21 #include "translator.icc"
22
23 void completize_extender (Spanner *sp);
24
25 class Extender_engraver : public Engraver
26 {
27   Stream_event *ev_;
28   Spanner *extender_;
29   Spanner *pending_extender_;
30
31 public:
32   TRANSLATOR_DECLARATIONS (Extender_engraver);
33
34 protected:
35   DECLARE_TRANSLATOR_LISTENER (extender);
36   DECLARE_ACKNOWLEDGER (lyric_syllable);
37   virtual void finalize ();
38   void stop_translation_timestep ();
39   void process_music ();
40 };
41
42 Extender_engraver::Extender_engraver ()
43 {
44   extender_ = 0;
45   pending_extender_ = 0;
46   ev_ = 0;
47 }
48
49 IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, extender);
50 void
51 Extender_engraver::listen_extender (Stream_event *ev)
52 {
53   ASSIGN_EVENT_ONCE (ev_, ev);
54 }
55
56 void
57 Extender_engraver::process_music ()
58 {
59   if (ev_)
60     extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
61 }
62
63 void
64 Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
65 {
66   Item *item = i.item ();
67   if (extender_)
68     extender_->set_bound (LEFT, item);
69
70   if (pending_extender_)
71     {
72       pending_extender_->set_object ("next", item->self_scm ());
73       completize_extender (pending_extender_);
74       pending_extender_ = 0;
75     }
76 }
77
78 void
79 Extender_engraver::stop_translation_timestep ()
80 {
81   if (extender_ || pending_extender_)
82     {
83       Context *voice = get_voice_to_lyrics (context ());
84       Grob *h = voice ? get_current_note_head (voice) : 0;
85
86       if (h)
87         {
88           if (extender_)
89             {
90               Pointer_group_interface::add_grob (extender_,
91                                                  ly_symbol2scm ("heads"), h);
92             }
93
94           if (pending_extender_)
95             {
96               Pointer_group_interface::add_grob (pending_extender_,
97                                                  ly_symbol2scm ("heads"), h);
98             }
99         }
100
101       if (extender_)
102         {
103           pending_extender_ = extender_;
104           extender_ = 0;
105         }
106     }
107
108   ev_ = 0;
109 }
110
111 void
112 completize_extender (Spanner *sp)
113 {
114   if (!sp->get_bound (RIGHT))
115     {
116       extract_item_set (sp, "heads", heads);
117       if (heads.size ())
118         sp->set_bound (RIGHT, heads.back ());
119     }
120 }
121
122 void
123 Extender_engraver::finalize ()
124 {
125   if (extender_)
126     {
127       completize_extender (extender_);
128
129       if (!extender_->get_bound (RIGHT))
130         extender_->warning (_ ("unterminated extender"));
131       extender_ = 0;
132     }
133
134   if (pending_extender_)
135     {
136       completize_extender (pending_extender_);
137
138       if (!pending_extender_->get_bound (RIGHT))
139         pending_extender_->warning (_ ("unterminated extender"));
140       pending_extender_ = 0;
141     }
142 }
143
144 ADD_ACKNOWLEDGER (Extender_engraver, lyric_syllable);
145 ADD_TRANSLATOR (Extender_engraver,
146                 /* doc */ "Create lyric extenders",
147                 /* create */ "LyricExtender",
148                 /* accept */ "extender-event",
149                 /* read */ "",
150                 /* write */ "");