]> git.donarmstrong.com Git - lilypond.git/blob - lily/unfolded-repeat-iterator.cc
release: 1.3.93
[lilypond.git] / lily / unfolded-repeat-iterator.cc
1 /*   
2   unfolded-repeat-iterator.cc --  implement Unfolded_repeat_iterator
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10
11 #include "repeated-music.hh"
12 #include "music-list.hh"
13 #include "unfolded-repeat-iterator.hh"
14 #include "debug.hh"
15 #include "translator-group.hh"
16
17 Unfolded_repeat_iterator::~Unfolded_repeat_iterator ()
18 {
19   delete current_iter_p_;
20 }
21
22 Unfolded_repeat_iterator::Unfolded_repeat_iterator ()
23 {
24   done_count_ =0;
25   current_iter_p_ =0;
26   do_main_b_ = false;
27   alternative_count_i_ =0;
28 }
29
30 /**
31
32 If we are in the body of the repeat always go to the current alternative.
33
34 If we are not in the body, then we are in an alternative.  If we are
35 fully unfolding, advance the current alternative and go back to main.
36 If we are semi-unfolding, advance the current alternative, and go to
37 the  alternative just set.
38    
39  */
40 void
41 Unfolded_repeat_iterator::next_element (bool side_effect) 
42 {
43   Repeated_music * repmus =dynamic_cast<Repeated_music *> (music_l_);
44   delete current_iter_p_;
45   current_iter_p_ =0;
46
47   bool do_repcommands = side_effect && repmus->volta_fold_b_;
48   
49   if (do_main_b_)
50     {
51       /*
52         we were busy doing the main body, so
53
54         - go to alternative if we're a volta
55
56         - do something intelligent when we're fully unfolding (fixcomment)
57        */
58       
59       here_mom_ += repmus->body ()->length_mom ();
60
61       if (!repmus->volta_fold_b_)
62         done_count_ ++;
63      
64       if (gh_pair_p (alternative_cons_))
65         {
66           current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
67           do_main_b_ = false;
68
69           if (repmus->volta_fold_b_)
70             {
71               String repstr = to_str (done_count_ + 1);
72               if (do_repcommands)
73                 add_repeat_command (gh_list (ly_symbol2scm ("volta"),
74                                              ly_str02scm (repstr.ch_C()), SCM_UNDEFINED));
75             }     
76         }
77       else if (done_count_ <  repmus->repeats_i_ && !repmus->volta_fold_b_) 
78         {
79           current_iter_p_ = get_iterator_p (repmus->body ());
80           do_main_b_ = true;
81         }
82     }
83   else
84     {
85       /*
86         we're not in the main part. So we're either in an alternative, or
87         we just finished.
88       */
89
90       /*
91         we're in the alternatives.  We move the pointer to the
92         next alternative.
93        */
94       if (alternative_cons_)
95         {
96           here_mom_ += unsmob_music (gh_car (alternative_cons_))->length_mom ();
97
98           if (repmus->volta_fold_b_ || 
99               repmus->repeats_i_ - done_count_  < alternative_count_i_)
100             alternative_cons_ = gh_cdr (alternative_cons_);
101           
102           if (do_repcommands)
103             add_repeat_command (gh_list (ly_symbol2scm ("volta"), SCM_BOOL_F, SCM_UNDEFINED));
104
105           
106           
107           /*
108             we've done the main body as well, but didn't go over the other
109             increment.  */
110           if (repmus->volta_fold_b_)
111             done_count_ ++;
112         }
113
114       /*
115         We still have alternatives left, so
116
117         if we're volta: traverse them
118
119         if we're full unfold: go back to main body.
120        */
121       
122       if (done_count_ < repmus->repeats_i_ && gh_pair_p (alternative_cons_))
123         {
124           if (do_repcommands)
125             {
126               String repstr = to_str (done_count_ + 1);
127               add_repeat_command (gh_list (ly_symbol2scm ("volta"),
128                                            ly_str02scm (repstr.ch_C()), SCM_UNDEFINED));
129               add_repeat_command (ly_symbol2scm ("end-repeat"));
130             }
131
132           
133           if (repmus->volta_fold_b_)
134             current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
135           else
136             {
137               current_iter_p_ = get_iterator_p (repmus->body ());
138               do_main_b_ = true;
139             }
140         }
141     }
142 }
143
144
145 bool
146 Unfolded_repeat_iterator::ok () const
147 {
148   return current_iter_p_ ;
149 }
150
151 Moment
152 Unfolded_repeat_iterator::pending_moment () const
153 {
154   return here_mom_ + current_iter_p_->pending_moment ();
155 }
156
157 void
158 Unfolded_repeat_iterator::construct_children ()
159 {
160   Repeated_music * mus =dynamic_cast<Repeated_music *> (music_l_);
161   
162   alternative_cons_ = (mus->alternatives ())
163     ? mus->alternatives ()->music_list ()
164     : SCM_EOL;
165
166   for (SCM p = alternative_cons_; gh_pair_p (p); p = gh_cdr (p))
167     alternative_count_i_ ++;
168
169   if (mus->body ())
170     {
171       current_iter_p_  = get_iterator_p (mus->body ());
172       do_main_b_ = true;
173     }
174   else if (gh_pair_p (alternative_cons_))
175     {
176       current_iter_p_ = get_iterator_p (unsmob_music (gh_car (alternative_cons_)));
177       do_main_b_ = false;
178     }
179 }
180
181 void
182 Unfolded_repeat_iterator::add_repeat_command (SCM what)
183 {
184   SCM reps = ly_symbol2scm ("repeatCommands");
185   SCM current_reps = report_to_l ()->get_property(reps);
186
187   Translator_group * where = report_to_l ()->where_defined (reps);
188   if (where
189       && current_reps == SCM_EOL || gh_pair_p (current_reps))
190     {
191       current_reps = gh_cons (what, current_reps);
192       where->set_property (reps, current_reps);
193     }
194 }
195
196 void
197 Unfolded_repeat_iterator::process (Moment m) 
198 {
199   if (!m)
200     {
201       if (dynamic_cast<Repeated_music*> (music_l_)->volta_fold_b_)
202         add_repeat_command (ly_symbol2scm ("start-repeat"));
203     }
204   while (1)
205     {
206       while (!current_iter_p_->ok ())
207         {
208           next_element(true);
209
210           if (!current_iter_p_)
211             return;
212         }
213       
214       if (m - here_mom_ >= current_iter_p_->pending_moment ())
215         current_iter_p_->process (m - here_mom_);
216       else
217         return;
218     }
219 }
220
221 void
222 Unfolded_repeat_iterator::skip (Moment until)
223 {
224   while (current_iter_p_)
225     {
226       Moment l =current_iter_p_->music_length_mom ();
227       if (l >= until - here_mom_)
228         current_iter_p_->skip (until - here_mom_);
229
230       if (current_iter_p_->ok ())
231         return ; 
232
233       next_element (false);
234     }
235 }
236
237 SCM
238 Unfolded_repeat_iterator::get_music (Moment until)const
239 {
240   SCM s = SCM_EOL;
241   if (until <  pending_moment ())
242     return s;
243
244
245   Unfolded_repeat_iterator * me
246     = dynamic_cast<Unfolded_repeat_iterator*> (this->clone ());
247   
248   while (me->ok ())
249     {
250       SCM nm = me->current_iter_p_->get_music (until -
251                                                me->here_mom_);
252       
253       s = gh_append2 (nm, s);
254       
255       Moment m = 0;
256       for (SCM i = nm; gh_pair_p(i); i = gh_cdr (i))
257         m = m >? unsmob_music (gh_car (i))->length_mom ();
258
259       if (m > Moment (0))
260         break ;
261       else
262         me->next_element (false);
263     }
264
265   delete me;
266   
267   return s;
268 }
269
270
271 Music_iterator* 
272 Unfolded_repeat_iterator::try_music_in_children (Music  * m) const
273 {
274   return  current_iter_p_->try_music (m);
275 }