/*
- unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator
-
- source file of the GNU LilyPond music typesetter
-
- (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-
- */
-
-/*
- This is too hairy. Maybe split into subclasses for volta and full
- unfold?
-
- */
-#include "music-iterator.hh"
-#include "repeated-music.hh"
-#include "music-list.hh"
-#include "debug.hh"
-#include "translator-group.hh"
-
-/**
- Iterate repeats. First do body, then alternatives one by one,
- optionally interspersed by the body.
- */
-class Unfolded_repeat_iterator : public Music_iterator
-{
- void add_repeat_command (SCM);
-
-public:
- VIRTUAL_COPY_CONS (Music_iterator);
- /**
- How often have we done the body (assuming bodies are interspersed.)?
+unfolded-repeat-iterator.cc -- implement Unfolded_repeat_iterator, Volta_repeat_iterator
- In volta: the number to print in the bracket.
- */
- int done_count_;
- static SCM constructor_cxx_function;
+source file of the GNU LilyPond music typesetter
- /*
- are we now busy doing the body?
- */
- bool do_main_b_;
+(c) 2002--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+*/
- /*
- are we doing volta's?
- */
- bool volta_b_;
- /** How far have we progressed into the repeat.
- This excludes the elt currently being iterated.
- */
- Moment here_mom_;
- int alternative_count_i_;
- Music_iterator * current_iter_p_;
-
- /// pointer to the alternative that will be processed next.
- SCM alternative_cons_;
- ~Unfolded_repeat_iterator ();
- Unfolded_repeat_iterator ();
- Unfolded_repeat_iterator (Unfolded_repeat_iterator const &);
-protected:
- virtual void construct_children ();
- virtual Moment pending_moment () const;
- virtual void process (Moment);
- virtual Music_iterator *try_music_in_children (Music *) const;
- virtual void skip (Moment);
- virtual SCM get_music (Moment) const;
-
- virtual bool ok () const;
- virtual void next_element (bool side_effect);
-};
+#include "music.hh"
+#include "sequential-iterator.hh"
+#include "translator-group.hh"
-class Volta_repeat_iterator : public Unfolded_repeat_iterator
+class Unfolded_repeat_iterator : public Sequential_iterator
{
public:
- Volta_repeat_iterator ();
- static SCM constructor_cxx_function;
- VIRTUAL_COPY_CONS (Music_iterator);
+ DECLARE_SCHEME_CALLBACK(constructor, ());
+protected:
+ virtual SCM get_music_list () const;
};
-
-Unfolded_repeat_iterator::~Unfolded_repeat_iterator ()
-{
- delete current_iter_p_;
-}
-
-Unfolded_repeat_iterator::Unfolded_repeat_iterator (Unfolded_repeat_iterator const &src)
- : Music_iterator (src)
-{
- done_count_ = src.done_count_;
- current_iter_p_ = (src.current_iter_p_)? src.current_iter_p_->clone () : 0;
- do_main_b_ = src.do_main_b_;
- volta_b_ = src.volta_b_;
- alternative_count_i_ = src.alternative_count_i_;
- alternative_cons_ = src.alternative_cons_;
-}
-
-Unfolded_repeat_iterator::Unfolded_repeat_iterator ()
-{
- done_count_ =0;
- current_iter_p_ =0;
- volta_b_ = false;
- do_main_b_ = false;
- alternative_count_i_ =0;
- alternative_cons_ = SCM_EOL;
-}
-
-/**
-
-If we are in the body of the repeat always go to the current alternative.
-
-If we are not in the body, then we are in an alternative. If we are
-fully unfolding, advance the current alternative and go back to main.
-If we are semi-unfolding, advance the current alternative, and go to
-the alternative just set.
-
- */
-void
-Unfolded_repeat_iterator::next_element (bool side_effect)
+SCM
+Unfolded_repeat_iterator::get_music_list () const
{
- Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l_);
- delete current_iter_p_;
- current_iter_p_ =0;
-
- bool do_repcommands = side_effect && volta_b_;
+ SCM l = SCM_EOL;
+ SCM *tail = &l;
- if (do_main_b_)
- {
- /*
- we were busy doing the main body, so
-
- - go to alternative if we're a volta
+ SCM body = get_music ()->get_mus_property ("element");
+ SCM alts = get_music ()->get_mus_property ("elements");
+ int alt_count = scm_ilength (alts);
+ int rep_count = gh_scm2int (get_music ()->get_mus_property ("repeat-count"));
- - make a :| if there are no alternatives
-
- - do something intelligent when we're fully unfolding (fixcomment)
- */
-
- here_mom_ += repmus->body ()->length_mom ();
+ for (int i = 0; i < rep_count; i++)
+ {
+ if (unsmob_music (body))
+ *tail = gh_cons (body, SCM_EOL) ;
- if (!volta_b_)
- done_count_ ++;
-
- if (gh_pair_p (alternative_cons_))
- {
- current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
- do_main_b_ = false;
+ tail = SCM_CDRLOC (*tail);
- if (volta_b_)
- {
- String repstr = to_str (done_count_ + 1) + ".";
-
- /*
- we're coming in from main, so we're always on the first repeat.
- */
- assert (done_count_ == 0);
-
- if (done_count_ == 0
- && alternative_count_i_ < repmus->repeat_count ())
- {
- done_count_ += repmus->repeat_count () - alternative_count_i_;
- repstr = "1.--" + to_str (done_count_ + 1) + ".";
- }
-
- if (do_repcommands)
- add_repeat_command (gh_list (ly_symbol2scm ("volta"),
- ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
- }
- }
- else if (volta_b_)
- {
- add_repeat_command (ly_symbol2scm ("end-repeat"));
- }
- else if (done_count_ < repmus->repeat_count ())
+ if (alt_count)
{
- current_iter_p_ = get_iterator_p (repmus->body ());
- do_main_b_ = true;
- }
+ *tail = gh_cons (gh_car (alts), SCM_EOL);
+ tail = SCM_CDRLOC (*tail);
+ if (i >= rep_count - alt_count)
+
+ alts = gh_cdr (alts);
+ }
}
- else
- {
- /*
- we're not in the main part. So we're either in an alternative, or
- we just finished.
- */
-
- /*
- we're in the alternatives. We move the pointer to the
- next alternative.
- */
- if (alternative_cons_)
- {
- here_mom_ += unsmob_music (gh_car (alternative_cons_))->length_mom ();
- if (volta_b_ ||
- repmus->repeat_count () - done_count_ < alternative_count_i_)
- alternative_cons_ = gh_cdr (alternative_cons_);
-
- if (do_repcommands)
- add_repeat_command (gh_list (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
-
-
-
- /*
- we've done the main body as well, but didn't go over the other
- increment. */
- if (volta_b_)
- done_count_ ++;
- }
-
- /*
- We still have alternatives left, so
+ return l;
+}
- if we're volta: traverse them
+class Volta_repeat_iterator : public Sequential_iterator
+{
+public:
+ DECLARE_SCHEME_CALLBACK(constructor, ());
+ Volta_repeat_iterator();
- if we're full unfold: go back to main body.
- */
-
- if (done_count_ < repmus->repeat_count () && gh_pair_p (alternative_cons_))
- {
- if (do_repcommands)
- {
- String repstr = to_str (done_count_ + 1) + ".";
- add_repeat_command (gh_list (ly_symbol2scm ("volta"),
- ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
- add_repeat_command (ly_symbol2scm ("end-repeat"));
- }
+ void add_repeat_command (SCM);
+protected:
+ virtual SCM get_music_list () const;
+ virtual void next_element (bool);
+ virtual void construct_children();
+ virtual void process (Moment);
-
- if (volta_b_)
- current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
- else
- {
- current_iter_p_ = get_iterator_p (repmus->body ());
- do_main_b_ = true;
- }
- }
- }
-}
+ bool first_time_;
+ int alt_count_;
+ int rep_count_;
+ int done_count_;
+};
-bool
-Unfolded_repeat_iterator::ok () const
+Volta_repeat_iterator::Volta_repeat_iterator()
{
- return current_iter_p_;
+ done_count_ = alt_count_ = rep_count_= 0;
+ first_time_ = true;
}
-Moment
-Unfolded_repeat_iterator::pending_moment () const
+SCM
+Volta_repeat_iterator::get_music_list()const
{
- return here_mom_ + current_iter_p_->pending_moment ();
+ return gh_cons (get_music ()->get_mus_property ("element"),
+ get_music ()->get_mus_property ("elements"));
}
void
-Unfolded_repeat_iterator::construct_children ()
+Volta_repeat_iterator::construct_children ()
{
- Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l_);
+ Sequential_iterator::construct_children();
- alternative_cons_ = (mus->alternatives ())
- ? mus->alternatives ()->music_list ()
- : SCM_EOL;
-
- for (SCM p = alternative_cons_; gh_pair_p (p); p = gh_cdr (p))
- alternative_count_i_ ++;
-
- if (mus->body ())
- {
- current_iter_p_ = get_iterator_p (mus->body ());
- do_main_b_ = true;
- }
- else if (gh_pair_p (alternative_cons_))
- {
- current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
- do_main_b_ = false;
- }
+ SCM alts = get_music ()->get_mus_property ("elements");
- while (current_iter_p_ && !current_iter_p_-> ok ())
- {
- next_element (true);
- }
+ alt_count_ = scm_ilength (alts);
+ rep_count_ = gh_scm2int (get_music ()->get_mus_property ("repeat-count"));
+ done_count_ = 0;
}
+
/*
TODO: add source information for debugging
*/
void
-Unfolded_repeat_iterator::add_repeat_command (SCM what)
+Volta_repeat_iterator::add_repeat_command (SCM what)
{
SCM reps = ly_symbol2scm ("repeatCommands");
- SCM current_reps = report_to_l ()->get_property (reps);
+ SCM current_reps = get_outlet ()->internal_get_property (reps);
- Translator_group * where = report_to_l ()->where_defined (reps);
+ Translator_group * where = get_outlet ()->where_defined (reps);
if (where
&& current_reps == SCM_EOL || gh_pair_p (current_reps))
{
current_reps = gh_cons (what, current_reps);
- where->set_property (reps, current_reps);
+ where->internal_set_property (reps, current_reps);
}
}
-void
-Unfolded_repeat_iterator::process (Moment m)
-{
- if (!m)
- {
- if (volta_b_)
- add_repeat_command (ly_symbol2scm ("start-repeat"));
- }
- while (1)
- {
- while (!current_iter_p_->ok ())
- {
- next_element (true);
-
- if (!current_iter_p_)
- return;
- }
-
- if (m - here_mom_ >= current_iter_p_->pending_moment ())
- current_iter_p_->process (m - here_mom_);
- else
- return;
- }
-}
void
-Unfolded_repeat_iterator::skip (Moment until)
+Volta_repeat_iterator::next_element (bool side_effect)
{
- while (current_iter_p_)
- {
- Moment l =current_iter_p_->music_length_mom ();
- if (l >= until - here_mom_)
- current_iter_p_->skip (until - here_mom_);
-
- if (current_iter_p_->ok ())
- return ;
+ done_count_ ++;
- next_element (false);
- }
-}
+ Sequential_iterator::next_element (side_effect);
-SCM
-Unfolded_repeat_iterator::get_music (Moment until)const
-{
- SCM s = SCM_EOL;
- if (until < pending_moment ())
- return s;
+ if (side_effect)
+ {
+ if (alt_count_)
+ {
+ String repstr = to_string (rep_count_ - alt_count_ + done_count_) + ".";
+ if (done_count_ > 1)
+ {
+ add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
+ if (done_count_ - 1 < alt_count_)
+ add_repeat_command (ly_symbol2scm ("end-repeat"));
+ }
- Unfolded_repeat_iterator * me
- = dynamic_cast<Unfolded_repeat_iterator*> (this->clone ());
-
- while (me->ok ())
- {
- SCM nm = me->current_iter_p_->get_music (until -
- me->here_mom_);
-
- s = gh_append2 (nm, s);
+
- Moment m = 0;
- for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
- m = m >? unsmob_music (gh_car (i))->length_mom ();
+ if (done_count_ == 1 && alt_count_ < rep_count_)
+ {
+ repstr = "1.--" + to_string (rep_count_ - alt_count_ + done_count_) + ".";
+ }
- if (m > Moment (0))
- break ;
+ if (done_count_ <= alt_count_)
+ add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
+ scm_makfrom0str (repstr.to_str0 ()), SCM_UNDEFINED));
+ }
else
- me->next_element (false);
+ {
+ add_repeat_command (ly_symbol2scm ("end-repeat"));
+ }
}
-
- delete me;
-
- return s;
}
-Music_iterator*
-Unfolded_repeat_iterator::try_music_in_children (Music * m) const
+void
+Volta_repeat_iterator::process (Moment m)
{
- return current_iter_p_->try_music (m);
+ if (first_time_)
+ {
+ add_repeat_command (ly_symbol2scm ("start-repeat"));
+ first_time_ = false;
+ }
+ Sequential_iterator::process(m);
}
-IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator);
-IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator);
-Volta_repeat_iterator::Volta_repeat_iterator ()
-{
- volta_b_ = true;
-}
+IMPLEMENT_CTOR_CALLBACK(Volta_repeat_iterator);
+IMPLEMENT_CTOR_CALLBACK(Unfolded_repeat_iterator);