]> git.donarmstrong.com Git - lilypond.git/blob - lily/extender-engraver.cc
* flower
[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--2005 Glen Prideaux <glenprideaux@iname.com>,
7   Han-Wen Nienhuys <hanwen@cs.uu.nl>,
8   Jan Nieuwenhuizen <janneke@gnu.org>
9 */
10
11 #include "context.hh"
12 #include "engraver.hh"
13 #include "group-interface.hh"
14 #include "item.hh"
15 #include "lyric-extender.hh"
16 #include "note-head.hh"
17 #include "warn.hh"
18
19 void completize_extender (Spanner *sp);
20
21 class Extender_engraver : public Engraver
22 {
23   Music *ev_;
24   Spanner *extender_;
25   Spanner *pending_extender_;
26
27 public:
28   TRANSLATOR_DECLARATIONS (Extender_engraver);
29
30 protected:
31   virtual void acknowledge_grob (Grob_info);
32   virtual void finalize ();
33   virtual bool try_music (Music *);
34   virtual void stop_translation_timestep ();
35   virtual void process_music ();
36 };
37
38 Extender_engraver::Extender_engraver ()
39 {
40   extender_ = 0;
41   pending_extender_ = 0;
42   ev_ = 0;
43 }
44
45 bool
46 Extender_engraver::try_music (Music *r)
47 {
48   if (!ev_)
49     {
50       ev_ = r;
51       return true;
52     }
53   return false;
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_grob (Grob_info i)
65 {
66   Item *item = dynamic_cast<Item *> (i.grob_);
67
68   if (item
69       && item->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
70     {
71       if (extender_)
72         extender_->set_bound (LEFT, item);
73
74       if (pending_extender_)
75         {
76           pending_extender_->set_property ("next", item->self_scm ());
77           completize_extender (pending_extender_);
78           pending_extender_ = 0;
79         }
80     }
81 }
82
83 void
84 Extender_engraver::stop_translation_timestep ()
85 {
86   if (extender_ || pending_extender_)
87     {
88       Context *voice = get_voice_to_lyrics (context ());
89       Grob *h = voice ? get_current_note_head (voice) : 0;
90
91       if (h)
92         {
93           if (extender_)
94             {
95               Pointer_group_interface::add_grob (extender_,
96                                                  ly_symbol2scm ("heads"), h);
97             }
98
99           if (pending_extender_)
100             {
101               Pointer_group_interface::add_grob (pending_extender_,
102                                                  ly_symbol2scm ("heads"), h);
103             }
104         }
105
106       if (extender_)
107         {
108           pending_extender_ = extender_;
109           extender_ = 0;
110         }
111     }
112
113   ev_ = 0;
114 }
115
116 void
117 completize_extender (Spanner *sp)
118 {
119   if (!sp->get_bound (RIGHT))
120     {
121       SCM heads = sp->get_property ("heads");
122       if (scm_is_pair (heads))
123         {
124           Item *it = dynamic_cast<Item *> (unsmob_grob (scm_car (heads)));
125           if (it)
126             sp->set_bound (RIGHT, it);
127         }
128     }
129 }
130
131 void
132 Extender_engraver::finalize ()
133 {
134   if (extender_)
135     {
136       completize_extender (extender_);
137
138       if (!extender_->get_bound (RIGHT))
139         extender_->warning (_ ("unterminated extender"));
140       extender_ = 0;
141     }
142
143   if (pending_extender_)
144     {
145       completize_extender (pending_extender_);
146
147       if (!pending_extender_->get_bound (RIGHT))
148         pending_extender_->warning (_ ("unterminated extender"));
149       pending_extender_ = 0;
150     }
151 }
152
153 ADD_TRANSLATOR (Extender_engraver,
154                 /* descr */ "Create lyric extenders",
155                 /* creats*/ "LyricExtender",
156                 /* accepts */ "extender-event",
157                 /* acks  */ "lyric-syllable-interface",
158                 /* reads */ "",
159                 /* write */ "");