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