2 unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
11 This is too hairy. Maybe split into subclasses for volta and full
15 #include "music-iterator.hh"
16 #include "repeated-music.hh"
17 #include "music-list.hh"
19 #include "translator-group.hh"
22 Iterate repeats. First do body, then alternatives one by one,
23 optionally interspersed by the body.
25 class Unfolded_repeat_iterator : public Music_iterator
27 void add_repeat_command (SCM);
30 VIRTUAL_COPY_CONS (Music_iterator);
32 How often have we done the body (assuming bodies are interspersed.)?
34 In volta: the number to print in the bracket.
37 static SCM constructor_cxx_function;
40 are we now busy doing the body?
50 /** How far have we progressed into the repeat.
51 This excludes the elt currently being iterated.
54 int alternative_count_i_;
55 Music_iterator * current_iter_p_;
57 /// pointer to the alternative that will be processed next.
58 SCM alternative_cons_;
59 ~Unfolded_repeat_iterator ();
60 Unfolded_repeat_iterator ();
61 Unfolded_repeat_iterator (Unfolded_repeat_iterator const &);
63 virtual void construct_children ();
64 virtual Moment pending_moment () const;
65 virtual void process (Moment);
66 virtual Music_iterator *try_music_in_children (Music *) const;
67 virtual void skip (Moment);
68 virtual SCM get_music (Moment) const;
70 virtual bool ok () const;
71 virtual void next_element (bool side_effect);
74 class Volta_repeat_iterator : public Unfolded_repeat_iterator
77 Volta_repeat_iterator ();
78 static SCM constructor_cxx_function;
79 VIRTUAL_COPY_CONS (Music_iterator);
84 Unfolded_repeat_iterator::~Unfolded_repeat_iterator ()
86 delete current_iter_p_;
89 Unfolded_repeat_iterator::Unfolded_repeat_iterator (Unfolded_repeat_iterator const &src)
90 : Music_iterator (src)
92 done_count_ = src.done_count_;
93 current_iter_p_ = (src.current_iter_p_)? src.current_iter_p_->clone () : 0;
94 do_main_b_ = src.do_main_b_;
95 volta_b_ = src.volta_b_;
96 here_mom_ = src.here_mom_;
97 alternative_count_i_ = src.alternative_count_i_;
98 alternative_cons_ = src.alternative_cons_;
101 Unfolded_repeat_iterator::Unfolded_repeat_iterator ()
107 here_mom_ = Moment (0);
108 alternative_count_i_ =0;
109 alternative_cons_ = SCM_EOL;
114 If we are in the body of the repeat always go to the current alternative.
116 If we are not in the body, then we are in an alternative. If we are
117 fully unfolding, advance the current alternative and go back to main.
118 If we are semi-unfolding, advance the current alternative, and go to
119 the alternative just set.
123 Unfolded_repeat_iterator::next_element (bool side_effect)
125 Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l ());
126 delete current_iter_p_;
129 bool do_repcommands = side_effect && volta_b_;
134 we were busy doing the main body, so
136 - go to alternative if we're a volta
138 - make a :| if there are no alternatives
140 - do something intelligent when we're fully unfolding (fixcomment)
143 here_mom_ += repmus->body ()->length_mom ();
148 if (gh_pair_p (alternative_cons_))
150 current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
155 String repstr = to_str (done_count_ + 1) + ".";
158 we're coming in from main, so we're always on the first repeat.
160 assert (done_count_ == 0);
163 && alternative_count_i_ < repmus->repeat_count ())
165 done_count_ += repmus->repeat_count () - alternative_count_i_;
166 repstr = "1.--" + to_str (done_count_ + 1) + ".";
170 add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
171 ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
176 add_repeat_command (ly_symbol2scm ("end-repeat"));
178 else if (done_count_ < repmus->repeat_count ())
180 current_iter_p_ = get_iterator_p (repmus->body ());
187 we're not in the main part. So we're either in an alternative, or
192 we're in the alternatives. We move the pointer to the
195 if (alternative_cons_)
197 here_mom_ += unsmob_music (ly_car (alternative_cons_))->length_mom ();
200 repmus->repeat_count () - done_count_ < alternative_count_i_)
201 alternative_cons_ = ly_cdr (alternative_cons_);
204 add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
209 we've done the main body as well, but didn't go over the other
216 We still have alternatives left, so
218 if we're volta: traverse them
220 if we're full unfold: go back to main body.
223 if (done_count_ < repmus->repeat_count () && gh_pair_p (alternative_cons_))
227 String repstr = to_str (done_count_ + 1) + ".";
228 add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
229 ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
230 add_repeat_command (ly_symbol2scm ("end-repeat"));
235 current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
238 current_iter_p_ = get_iterator_p (repmus->body ());
247 Unfolded_repeat_iterator::ok () const
249 return current_iter_p_;
253 Unfolded_repeat_iterator::pending_moment () const
255 return here_mom_ + current_iter_p_->pending_moment ();
259 Unfolded_repeat_iterator::construct_children ()
261 Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l ());
263 alternative_cons_ = (mus->alternatives ())
264 ? mus->alternatives ()
267 for (SCM p = alternative_cons_; gh_pair_p (p); p = ly_cdr (p))
268 alternative_count_i_ ++;
272 current_iter_p_ = get_iterator_p (mus->body ());
275 else if (gh_pair_p (alternative_cons_))
277 current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
281 while (current_iter_p_ && !current_iter_p_-> ok ())
288 TODO: add source information for debugging
291 Unfolded_repeat_iterator::add_repeat_command (SCM what)
293 SCM reps = ly_symbol2scm ("repeatCommands");
294 SCM current_reps = report_to_l ()->internal_get_property (reps);
296 Translator_group * where = report_to_l ()->where_defined (reps);
298 && current_reps == SCM_EOL || gh_pair_p (current_reps))
300 current_reps = gh_cons (what, current_reps);
301 where->internal_set_property (reps, current_reps);
306 Unfolded_repeat_iterator::process (Moment m)
311 add_repeat_command (ly_symbol2scm ("start-repeat"));
315 while (!current_iter_p_->ok ())
319 if (!current_iter_p_)
323 if (m - here_mom_ >= current_iter_p_->pending_moment ())
324 current_iter_p_->process (m - here_mom_);
331 Unfolded_repeat_iterator::skip (Moment until)
333 while (current_iter_p_)
335 Moment l =current_iter_p_->music_length_mom ();
336 if (l >= until - here_mom_)
337 current_iter_p_->skip (until - here_mom_);
339 if (current_iter_p_->ok ())
342 next_element (false);
347 Unfolded_repeat_iterator::get_music (Moment until)const
350 if (until < pending_moment ())
354 Unfolded_repeat_iterator * me
355 = dynamic_cast<Unfolded_repeat_iterator*> (this->clone ());
359 SCM nm = me->current_iter_p_->get_music (until -
362 s = gh_append2 (nm, s);
365 for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
366 m = m >? unsmob_music (ly_car (i))->length_mom ();
371 me->next_element (false);
381 Unfolded_repeat_iterator::try_music_in_children (Music * m) const
383 return current_iter_p_->try_music (m);
386 IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator);
387 IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator);
389 Volta_repeat_iterator::Volta_repeat_iterator ()