]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-iterator.cc
* lily/musical-request.cc: do ADD_MUSIC for String_number_req.
[lilypond.git] / lily / sequential-iterator.cc
1 /*
2   Sequential_iterator.cc -- implement Sequential_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "translator-group.hh"
10
11 #include "sequential-iterator.hh"
12 #include "music-list.hh"
13
14 Grace_fixup *copy_grace_fixups (Grace_fixup* src);
15 Grace_fixup *get_grace_fixups (SCM cursor);
16
17 /*
18   
19   TODO: handling of grace notes is exquisite pain.  This handling
20   should be formally specified and then the implementation verified.
21
22 */
23
24 /*
25   Invariant for the data structure.
26
27
28   if (gh_pair_p (cursor_))
29     iter_->music_ == unsmob_music (ly_car (cursor_))
30   else
31     iter_ == 0;
32
33   The length of musiclist from start to up to cursor_ (cursor_ not
34   including), is summed
35
36   here_mom_  = sum (length (musiclist [start ... cursor>))  %)  
37   
38  */
39 Sequential_iterator::Sequential_iterator ()
40 {
41   here_mom_ = Moment (0);
42   grace_fixups_ = 0;
43   iter_ =0;
44 }
45
46 SCM 
47 Sequential_iterator::get_music_list () const
48 {
49   return SCM_EOL;
50 }
51
52 Sequential_iterator::Sequential_iterator (Sequential_iterator const &src)
53   : Music_iterator (src)
54 {
55   grace_fixups_ = copy_grace_fixups (src.grace_fixups_);
56   cursor_ = src.cursor_;
57   list_ = src.cursor_;
58   here_mom_ = src.here_mom_;
59   if (src.iter_)
60     iter_ = src.iter_->clone ();
61   else
62     iter_ = 0;
63
64   if (iter_)
65     scm_gc_unprotect_object (iter_->self_scm());
66 }
67
68 void
69 Sequential_iterator::derived_mark ()const
70 {
71   if (iter_)
72     scm_gc_mark (iter_->self_scm());
73 }
74
75
76 Grace_fixup *
77 get_grace_fixups (SCM cursor)
78 {
79   Moment here;
80   Moment last (-1);
81   Grace_fixup *head = 0;
82   Grace_fixup **tail = &head;
83
84   for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
85     {
86       Music * mus = unsmob_music (ly_car (cursor));
87       Moment s = mus->start_mom ();
88       Moment l =mus->length_mom () - s;
89
90       if (s.grace_part_)
91         {
92           if (last != Moment (-1))
93             {
94               Grace_fixup *p =new Grace_fixup;
95               p->start_ = last;
96               p->length_ = here - last;
97               p->grace_start_ = s.grace_part_;
98               p->next_ = 0;
99               *tail = p;
100               tail = &(*tail)->next_; 
101             }
102
103           here.grace_part_ = s.grace_part_;
104         }
105       
106       if (l.to_bool())
107         {
108           last = here;
109           here += l;
110         }
111     }
112   return  head;
113 }
114
115 Grace_fixup *
116 copy_grace_fixups (Grace_fixup* src)
117 {
118   Grace_fixup * head = 0;
119   Grace_fixup **dest = &head;
120
121   while (src)
122     {
123       *dest = new Grace_fixup (*src);
124       dest = & (*dest)->next_;
125       src = src ->next_;
126     }
127
128   return head;
129 }
130
131 void
132 Sequential_iterator::construct_children ()
133 {
134   list_ = get_music_list ();
135   cursor_ = list_; 
136
137   iter_ = 0;
138   if (gh_pair_p (cursor_))
139     {
140       Music *m  =unsmob_music (ly_car (cursor_));
141       iter_ = unsmob_iterator ( get_iterator (m));
142     }
143   
144   while (iter_ && !iter_->ok ())
145     {
146       next_element (true);
147     }
148
149   here_mom_ = get_music ()->start_mom ();
150   grace_fixups_ = get_grace_fixups (cursor_);
151
152   /*
153     iter_->ok () is tautology, but what the heck.
154    */
155   if (iter_ && iter_->ok ()) 
156     descend_to_child ();
157 }
158
159
160 /*
161   maintain invariants: change cursor, iter and here_mom_ in one fell
162   swoop.
163 */
164 void
165 Sequential_iterator::next_element (bool side_effect)
166 {
167   Moment len =iter_->music_length_mom () - iter_->music_start_mom ();
168   assert (!grace_fixups_  || grace_fixups_->start_ >= here_mom_);
169   
170   if (len.main_part_ && grace_fixups_ &&
171       grace_fixups_->start_ == here_mom_)
172     {
173       here_mom_ += grace_fixups_->length_;
174       here_mom_.grace_part_ += grace_fixups_->grace_start_;
175
176       Grace_fixup * n =grace_fixups_->next_;
177       delete grace_fixups_;
178       grace_fixups_ = n;
179     }
180   else if (len.grace_part_ && !len.main_part_)
181     {
182       here_mom_.grace_part_ =0;
183     }
184   else
185     {
186       /*
187         !len.grace_part_ || len.main_part_
188
189         We skip over a big chunk (mainpart != 0). Any starting graces
190         in that chunk should be in len.grace_part_
191
192       */
193       here_mom_ += len;
194     }
195   
196   cursor_ = ly_cdr (cursor_);
197
198   if (gh_pair_p (cursor_))
199     iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
200   else
201     iter_ = 0;
202 }
203
204 /*
205   move to context of child iterator if it is deeper down in the
206   hierarchy.
207   */
208 void
209 Sequential_iterator::descend_to_child ()
210 {
211 }
212
213
214 /*
215   Retrieve all music (starting at HERE), until a music with length L >
216   0 is found.  From the precondition, we know that UNTIL is later than
217   the earliest event. Hence we know
218   
219   L >= (UNTIL - HERE)
220
221   so something that comes after this thing with L > 0 happens after
222
223   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
224
225   Hence all events after the one with L>0 are uninteresting, so we
226   ignore them.
227   
228 */
229
230 SCM
231 Sequential_iterator::get_pending_events (Moment until)const
232 {
233   SCM s = SCM_EOL;
234   if (until <  pending_moment ())
235     return s;
236
237   Sequential_iterator * me =
238     dynamic_cast<Sequential_iterator*> (clone ());
239   while (me->ok ())
240     {
241       SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
242       s = gh_append2 (nm, s);
243       
244       Moment m = 0;
245       for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
246         {
247           Music *mus=unsmob_music (ly_car (i));
248           m = m >? (mus->length_mom () - mus->start_mom ());
249         }
250       if (m > Moment (0))
251         break ;
252       else
253         me->next_element (false);
254     }
255
256   scm_gc_unprotect_object (me->self_scm());
257   return s;
258 }
259
260
261 /*
262   Skip events till UNTIL. We don't do any other side effects such as
263   descending to child iterator contexts, because they might depend on
264   \context specs and \translator changes being executed
265  */
266 void
267 Sequential_iterator::skip (Moment until)
268 {
269   while (ok ())
270     {
271       if (grace_fixups_ &&
272           grace_fixups_->start_ == here_mom_
273           && (grace_fixups_->start_ + grace_fixups_->length_
274               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
275         {
276           /*
277             do the stuff/note/rest preceding a grace.
278            */
279           iter_->skip (iter_->music_length_mom ());
280         }
281       else if (iter_->music_length_mom () >= until - here_mom_)
282         iter_->skip (until - here_mom_ + iter_->music_start_mom ());
283
284       if (iter_->ok ())
285         return ; 
286
287       next_element (false);
288     }
289 }
290
291 void
292 Sequential_iterator::process (Moment until)
293 {
294   while (iter_)
295     {
296       if (grace_fixups_ &&
297           grace_fixups_->start_ == here_mom_
298           && (grace_fixups_->start_ + grace_fixups_->length_
299               + Moment (Rational (0), grace_fixups_->grace_start_) == until))
300         {
301           /*
302             do the stuff/note/rest preceding a grace.
303            */
304           iter_->process (iter_->music_length_mom ());
305         }
306       else
307         iter_->process (until - here_mom_ + iter_->music_start_mom ());
308
309       /*
310         if the iter is still OK, there must be events left that have
311         
312           TIME > LEFT
313           
314       */
315       if (iter_->ok ())
316         return ;
317
318       descend_to_child ();
319       next_element (true);
320     }
321 }
322
323 Moment
324 Sequential_iterator::pending_moment () const
325 {
326   Moment cp = iter_->pending_moment ();
327
328   /*
329     Fix-up a grace note halfway in the music.
330   */
331   if (grace_fixups_ && here_mom_ == grace_fixups_->start_
332       && grace_fixups_->length_ + iter_->music_start_mom () == cp)
333     {
334       return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
335     }
336
337   /*
338     Fix-up a grace note at  the start of the music.
339   */
340   return cp + here_mom_ - iter_->music_start_mom ();
341 }
342
343
344 bool
345 Sequential_iterator::ok () const
346 {
347   return iter_;
348 }
349
350 Music_iterator*
351 Sequential_iterator::try_music_in_children (Music *m) const
352
353   return iter_ ? iter_->try_music (m) : 0;
354 }
355
356 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);