]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/unfolded-repeat-iterator.cc
release: 1.5.19
[lilypond.git] / lily / unfolded-repeat-iterator.cc
index 6395987a1df84f235dba6c6fbabeacdadaea4b75..7dd93bd1dcfa8ad4950ff6c8d93da9eb02c979f7 100644 (file)
   
   source file of the GNU LilyPond music typesetter
   
-  (c) 1999--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  (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 "unfolded-repeat-iterator.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.)?
+
+     In volta: the number to print in the bracket.
+   */
+  int done_count_;
+  static SCM constructor_cxx_function; 
+
+  /*
+    are we now busy doing the body?
+
+   */
+  bool do_main_b_;
+
+  /*
+    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);
+};
+
+class Volta_repeat_iterator : public Unfolded_repeat_iterator
+{
+public:
+  Volta_repeat_iterator ();
+  static  SCM constructor_cxx_function;
+  VIRTUAL_COPY_CONS (Music_iterator);
+};
+
+
+
 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;
 }
 
 /**
@@ -38,28 +118,64 @@ the  alternative just set.
    
  */
 void
-Unfolded_repeat_iterator::next_element () 
+Unfolded_repeat_iterator::next_element (bool side_effect
 {
-  Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l_);
+  Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l ());
   delete current_iter_p_;
   current_iter_p_ =0;
 
-
+  bool do_repcommands = side_effect && volta_b_;
+  
   if (do_main_b_)
     {
-      done_mom_ += mus->body ()->length_mom ();
+      /*
+       we were busy doing the main body, so
+
+       - go to alternative if we're a volta
 
-      if (!mus->volta_fold_b_)
+       - make a :| if there are no alternatives   
+       
+       - do something intelligent when we're fully unfolding (fixcomment)
+       */
+      
+      here_mom_ += repmus->body ()->length_mom ();
+
+      if (!volta_b_)
        done_count_ ++;
      
       if (gh_pair_p (alternative_cons_))
        {
-         current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
+         current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
          do_main_b_ = false;
+
+         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 (scm_list_n (ly_symbol2scm ("volta"),
+                                            ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
+           }     
        }
-      else if (done_count_ <  mus->repeats_i_ && !mus->volta_fold_b_) 
+      else if (volta_b_)
        {
-         current_iter_p_ = get_iterator_p (mus->body ());
+         add_repeat_command (ly_symbol2scm ("end-repeat"));
+       }
+      else if (done_count_ <  repmus->repeat_count ())
+       {
+         current_iter_p_ = get_iterator_p (repmus->body ());
          do_main_b_ = true;
        }
     }
@@ -69,28 +185,55 @@ Unfolded_repeat_iterator::next_element ()
        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_)
        {
-         done_mom_ += unsmob_music (gh_car (alternative_cons_))->length_mom ();
+         here_mom_ += unsmob_music (ly_car (alternative_cons_))->length_mom ();
+
+         if (volta_b_ || 
+             repmus->repeat_count () - done_count_  < alternative_count_i_)
+           alternative_cons_ = ly_cdr (alternative_cons_);
+         
+         if (do_repcommands)
+           add_repeat_command (scm_list_n (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
 
-         if (mus->volta_fold_b_ || 
-             mus->repeats_i_ - done_count_  < alternative_count_i_)
-           alternative_cons_ = gh_cdr (alternative_cons_);
+         
          
          /*
            we've done the main body as well, but didn't go over the other
            increment.  */
-         if (mus->volta_fold_b_)
+         if (volta_b_)
            done_count_ ++;
        }
+
+      /*
+       We still have alternatives left, so
+
+       if we're volta: traverse them
+
+       if we're full unfold: go back to main body.
+       */
       
-      if (done_count_ < mus->repeats_i_ && gh_pair_p (alternative_cons_))
+      if (done_count_ < repmus->repeat_count () && gh_pair_p (alternative_cons_))
        {
-         if (mus->volta_fold_b_)
-           current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
+         if (do_repcommands)
+           {
+             String repstr = to_str (done_count_ + 1) + ".";
+             add_repeat_command (scm_list_n (ly_symbol2scm ("volta"),
+                                          ly_str02scm (repstr.ch_C ()), SCM_UNDEFINED));
+             add_repeat_command (ly_symbol2scm ("end-repeat"));
+           }
+
+         
+         if (volta_b_)
+           current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
          else
            {
-             current_iter_p_ = get_iterator_p (mus->body ());
+             current_iter_p_ = get_iterator_p (repmus->body ());
              do_main_b_ = true;
            }
        }
@@ -101,25 +244,25 @@ Unfolded_repeat_iterator::next_element ()
 bool
 Unfolded_repeat_iterator::ok () const
 {
-  return current_iter_p_ ;
+  return current_iter_p_;
 }
 
 Moment
-Unfolded_repeat_iterator::next_moment () const
+Unfolded_repeat_iterator::pending_moment () const
 {
-  return done_mom_ + current_iter_p_->next_moment ();
+  return here_mom_ + current_iter_p_->pending_moment ();
 }
 
 void
 Unfolded_repeat_iterator::construct_children ()
 {
-  Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l_);
+  Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l ());
   
   alternative_cons_ = (mus->alternatives ())
-    ? mus->alternatives ()->music_list ()
+    ? mus->alternatives ()
     : SCM_EOL;
 
-  for (SCM p = alternative_cons_; gh_pair_p (p); p = gh_cdr (p))
+  for (SCM p = alternative_cons_; gh_pair_p (p); p = ly_cdr (p))
     alternative_count_i_ ++;
 
   if (mus->body ())
@@ -129,51 +272,119 @@ Unfolded_repeat_iterator::construct_children ()
     }
   else if (gh_pair_p (alternative_cons_))
     {
-      current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
+      current_iter_p_ = get_iterator_p (unsmob_music (ly_car (alternative_cons_)));
       do_main_b_ = false;
     }
+
+  while (current_iter_p_ && !current_iter_p_-> ok ())
+    {
+      next_element (true);
+    }
 }
 
+/*
+  TODO: add source information for debugging
+ */
 void
-Unfolded_repeat_iterator::do_process_and_next (Moment m) 
+Unfolded_repeat_iterator::add_repeat_command (SCM what)
 {
-  if (!m)
+  SCM reps = ly_symbol2scm ("repeatCommands");
+  SCM current_reps = report_to_l ()->get_property (reps);
+
+  Translator_group * where = report_to_l ()->where_defined (reps);
+  if (where
+      && current_reps == SCM_EOL || gh_pair_p (current_reps))
     {
-      Music_iterator *yeah = try_music (music_l_);
-      if (yeah)
-       set_translator (yeah->report_to_l ());
-      else
-       music_l_->origin ()->warning ( _("no one to print a volta bracket"));
+      current_reps = gh_cons (what, current_reps);
+      where->internal_set_property (reps, current_reps);
+    }
+}
+
+void
+Unfolded_repeat_iterator::process (Moment m) 
+{
+  if (!m.to_bool ())
+    {
+      if (volta_b_)
+       add_repeat_command (ly_symbol2scm ("start-repeat"));
     }
   while (1)
     {
       while (!current_iter_p_->ok ())
        {
-         next_element();
+         next_element (true);
 
          if (!current_iter_p_)
            return;
        }
       
-      if (m - done_mom_ >= current_iter_p_->next_moment ())
-       current_iter_p_->process_and_next (m - done_mom_);
+      if (m - here_mom_ >= current_iter_p_->pending_moment ())
+       current_iter_p_->process (m - here_mom_);
       else
        return;
     }
 }
-  
+
 void
-Unfolded_repeat_iterator::do_print () const
+Unfolded_repeat_iterator::skip (Moment until)
+{
+  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 ; 
+
+      next_element (false);
+    }
+}
+
+SCM
+Unfolded_repeat_iterator::get_music (Moment until)const
 {
-#ifndef NPRINT
-  DEBUG_OUT << "count " << done_count_ << "done time " << Rational (done_mom_) << '\n';
-  DEBUG_OUT << "current: ";
-  current_iter_p_->print();
-#endif
+  SCM s = SCM_EOL;
+  if (until <  pending_moment ())
+    return s;
+
+
+  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 = ly_cdr (i))
+       m = m >? unsmob_music (ly_car (i))->length_mom ();
+
+      if (m > Moment (0))
+       break ;
+      else
+       me->next_element (false);
+    }
+
+  delete me;
+  
+  return s;
 }
 
+
 Music_iterator* 
 Unfolded_repeat_iterator::try_music_in_children (Music  * m) const
 {
   return  current_iter_p_->try_music (m);
 }
+
+IMPLEMENT_CTOR_CALLBACK (Unfolded_repeat_iterator);
+IMPLEMENT_CTOR_CALLBACK (Volta_repeat_iterator);
+
+Volta_repeat_iterator::Volta_repeat_iterator ()
+{
+  volta_b_ = true;
+}