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