]> git.donarmstrong.com Git - lilypond.git/blob - lily/extender-engraver.cc
* lily/parser.yy (Music_list): add error-found to music with errors.
[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--2004 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
39 Extender_engraver::Extender_engraver ()
40 {
41   extender_ = 0;
42   pending_extender_ = 0;
43   ev_ = 0;
44 }
45
46 bool
47 Extender_engraver::try_music (Music *r)
48 {
49   if (!ev_)
50     {
51       ev_ = r;
52       return true;
53     }
54   return false;
55 }
56
57 void
58 Extender_engraver::process_music ()
59 {
60   if (ev_)
61     extender_ = make_spanner ("LyricExtender", ev_->self_scm ());
62 }
63
64 void
65 Extender_engraver::acknowledge_grob (Grob_info i)
66 {
67   Item *item = dynamic_cast<Item*> (i.grob_);
68
69   if (item
70       && item->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
71     {
72       if (extender_)
73         extender_->set_bound (LEFT, item);
74
75       if (pending_extender_)
76         {
77           pending_extender_->set_property ("next", item->self_scm ());
78           completize_extender (pending_extender_);
79           pending_extender_ = 0;
80         }
81     }
82 }
83
84 void
85 Extender_engraver::stop_translation_timestep ()
86 {
87   if (extender_ || pending_extender_)
88     {
89       Context *voice = get_voice_to_lyrics (context ());
90       Grob *h = voice ? get_current_note_head (voice) : 0;
91
92       if (h)
93         {
94           if (extender_)
95             {
96               Pointer_group_interface::add_grob (extender_,
97                                                  ly_symbol2scm ("heads"), h);
98             }
99           
100           if (pending_extender_)
101             {
102               Pointer_group_interface::add_grob (pending_extender_,
103                                                  ly_symbol2scm ("heads"), h);
104             }
105         }
106       
107       if (extender_)
108         {
109           pending_extender_ = extender_;
110           extender_ = 0;
111         }
112     }
113
114   ev_ = 0;
115 }
116
117 void
118 completize_extender (Spanner *sp)
119 {
120   if (!sp->get_bound (RIGHT))
121     {
122       SCM heads = sp->get_property ("heads");
123       if (scm_is_pair (heads))
124         {
125           Item *it = dynamic_cast<Item*> (unsmob_grob (scm_car (heads)));
126           if (it)
127             sp->set_bound (RIGHT, it);
128         }
129     }
130 }
131
132 void
133 Extender_engraver::finalize ()
134 {
135   if (extender_)
136     {
137       completize_extender (extender_);
138
139       if (!extender_->get_bound (RIGHT))
140         extender_->warning (_ ("unterminated extender"));
141       extender_ = 0;
142     }
143
144   if (pending_extender_)
145     {
146       completize_extender (pending_extender_);
147
148       if (!pending_extender_->get_bound (RIGHT))
149         pending_extender_->warning (_ ("unterminated extender"));
150       pending_extender_ =0;
151     }
152 }
153
154
155 ENTER_DESCRIPTION (Extender_engraver,
156 /* descr */       "Create lyric extenders",
157 /* creats*/       "LyricExtender",
158 /* accepts */     "extender-event",
159 /* acks  */       "lyric-syllable-interface",
160 /* reads */       "",
161 /* write */       "");