2 unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2001 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 alternative_count_i_
= src
.alternative_count_i_
;
97 alternative_cons_
= src
.alternative_cons_
;
100 Unfolded_repeat_iterator::Unfolded_repeat_iterator ()
106 alternative_count_i_
=0;
107 alternative_cons_
= SCM_EOL
;
112 If we are in the body of the repeat always go to the current alternative.
114 If we are not in the body, then we are in an alternative. If we are
115 fully unfolding, advance the current alternative and go back to main.
116 If we are semi-unfolding, advance the current alternative, and go to
117 the alternative just set.
121 Unfolded_repeat_iterator::next_element (bool side_effect
)
123 Repeated_music
* repmus
=dynamic_cast<Repeated_music
*> (music_l ());
124 delete current_iter_p_
;
127 bool do_repcommands
= side_effect
&& volta_b_
;
132 we were busy doing the main body, so
134 - go to alternative if we're a volta
136 - make a :| if there are no alternatives
138 - do something intelligent when we're fully unfolding (fixcomment)
141 here_mom_
+= repmus
->body ()->length_mom ();
146 if (gh_pair_p (alternative_cons_
))
148 current_iter_p_
= get_iterator_p (unsmob_music (gh_car (alternative_cons_
)));
153 String repstr
= to_str (done_count_
+ 1) + ".";
156 we're coming in from main, so we're always on the first repeat.
158 assert (done_count_
== 0);
161 && alternative_count_i_
< repmus
->repeat_count ())
163 done_count_
+= repmus
->repeat_count () - alternative_count_i_
;
164 repstr
= "1.--" + to_str (done_count_
+ 1) + ".";
168 add_repeat_command (gh_list (ly_symbol2scm ("volta"),
169 ly_str02scm (repstr
.ch_C ()), SCM_UNDEFINED
));
174 add_repeat_command (ly_symbol2scm ("end-repeat"));
176 else if (done_count_
< repmus
->repeat_count ())
178 current_iter_p_
= get_iterator_p (repmus
->body ());
185 we're not in the main part. So we're either in an alternative, or
190 we're in the alternatives. We move the pointer to the
193 if (alternative_cons_
)
195 here_mom_
+= unsmob_music (gh_car (alternative_cons_
))->length_mom ();
198 repmus
->repeat_count () - done_count_
< alternative_count_i_
)
199 alternative_cons_
= gh_cdr (alternative_cons_
);
202 add_repeat_command (gh_list (ly_symbol2scm ("volta"), SCM_BOOL_F
, SCM_UNDEFINED
));
207 we've done the main body as well, but didn't go over the other
214 We still have alternatives left, so
216 if we're volta: traverse them
218 if we're full unfold: go back to main body.
221 if (done_count_
< repmus
->repeat_count () && gh_pair_p (alternative_cons_
))
225 String repstr
= to_str (done_count_
+ 1) + ".";
226 add_repeat_command (gh_list (ly_symbol2scm ("volta"),
227 ly_str02scm (repstr
.ch_C ()), SCM_UNDEFINED
));
228 add_repeat_command (ly_symbol2scm ("end-repeat"));
233 current_iter_p_
= get_iterator_p (unsmob_music (gh_car (alternative_cons_
)));
236 current_iter_p_
= get_iterator_p (repmus
->body ());
245 Unfolded_repeat_iterator::ok () const
247 return current_iter_p_
;
251 Unfolded_repeat_iterator::pending_moment () const
253 return here_mom_
+ current_iter_p_
->pending_moment ();
257 Unfolded_repeat_iterator::construct_children ()
259 Repeated_music
* mus
=dynamic_cast<Repeated_music
*> (music_l ());
261 alternative_cons_
= (mus
->alternatives ())
262 ? mus
->alternatives ()->music_list ()
265 for (SCM p
= alternative_cons_
; gh_pair_p (p
); p
= gh_cdr (p
))
266 alternative_count_i_
++;
270 current_iter_p_
= get_iterator_p (mus
->body ());
273 else if (gh_pair_p (alternative_cons_
))
275 current_iter_p_
= get_iterator_p (unsmob_music (gh_car (alternative_cons_
)));
279 while (current_iter_p_
&& !current_iter_p_
-> ok ())
286 TODO: add source information for debugging
289 Unfolded_repeat_iterator::add_repeat_command (SCM what
)
291 SCM reps
= ly_symbol2scm ("repeatCommands");
292 SCM current_reps
= report_to_l ()->get_property (reps
);
294 Translator_group
* where
= report_to_l ()->where_defined (reps
);
296 && current_reps
== SCM_EOL
|| gh_pair_p (current_reps
))
298 current_reps
= gh_cons (what
, current_reps
);
299 where
->set_property (reps
, current_reps
);
304 Unfolded_repeat_iterator::process (Moment m
)
309 add_repeat_command (ly_symbol2scm ("start-repeat"));
313 while (!current_iter_p_
->ok ())
317 if (!current_iter_p_
)
321 if (m
- here_mom_
>= current_iter_p_
->pending_moment ())
322 current_iter_p_
->process (m
- here_mom_
);
329 Unfolded_repeat_iterator::skip (Moment until
)
331 while (current_iter_p_
)
333 Moment l
=current_iter_p_
->music_length_mom ();
334 if (l
>= until
- here_mom_
)
335 current_iter_p_
->skip (until
- here_mom_
);
337 if (current_iter_p_
->ok ())
340 next_element (false);
345 Unfolded_repeat_iterator::get_music (Moment until
)const
348 if (until
< pending_moment ())
352 Unfolded_repeat_iterator
* me
353 = dynamic_cast<Unfolded_repeat_iterator
*> (this->clone ());
357 SCM nm
= me
->current_iter_p_
->get_music (until
-
360 s
= gh_append2 (nm
, s
);
363 for (SCM i
= nm
; gh_pair_p (i
); i
= gh_cdr (i
))
364 m
= m
>? unsmob_music (gh_car (i
))->length_mom ();
369 me
->next_element (false);
379 Unfolded_repeat_iterator::try_music_in_children (Music
* m
) const
381 return current_iter_p_
->try_music (m
);
384 IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator
);
385 IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator
);
387 Volta_repeat_iterator::Volta_repeat_iterator ()