2 Sequential_iterator.cc -- implement Sequential_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "translator-group.hh"
11 #include "sequential-iterator.hh"
12 #include "music-list.hh"
14 Grace_fixup *copy_grace_fixups (Grace_fixup* src);
15 Grace_fixup *get_grace_fixups (SCM cursor);
19 TODO: handling of grace notes is exquisite pain. This handling
20 should be formally specified and then the implementation verified.
25 Invariant for the data structure.
28 if (gh_pair_p (cursor_))
29 iter_->music_ == unsmob_music (ly_car (cursor_))
33 The length of musiclist from start to up to cursor_ (cursor_ not
36 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
39 Sequential_iterator::Sequential_iterator ()
41 here_mom_ = Moment (0);
49 Sequential_iterator::get_music_list () const
55 Sequential_iterator::do_quit ()
62 Sequential_iterator::Sequential_iterator (Sequential_iterator const &src)
63 : Music_iterator (src)
65 grace_fixups_ = copy_grace_fixups (src.grace_fixups_);
66 cursor_ = src.cursor_;
68 here_mom_ = src.here_mom_;
69 iter_ = (src.iter_) ? src.iter_->clone () : 0;
72 scm_gc_unprotect_object (iter_->self_scm());
76 Sequential_iterator::derived_mark ()const
79 scm_gc_mark (iter_->self_scm());
81 scm_gc_mark (cursor_);
86 get_grace_fixups (SCM cursor)
90 Grace_fixup *head = 0;
91 Grace_fixup **tail = &head;
93 for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
95 Music * mus = unsmob_music (ly_car (cursor));
96 Moment s = mus->start_mom ();
97 Moment l =mus->length_mom () - s;
101 if (last != Moment (-1))
103 Grace_fixup *p =new Grace_fixup;
105 p->length_ = here - last;
106 p->grace_start_ = s.grace_part_;
109 tail = &(*tail)->next_;
112 here.grace_part_ = s.grace_part_;
125 copy_grace_fixups (Grace_fixup* src)
127 Grace_fixup * head = 0;
128 Grace_fixup **dest = &head;
132 *dest = new Grace_fixup (*src);
133 dest = & (*dest)->next_;
141 Sequential_iterator::construct_children ()
143 list_ = get_music_list ();
147 if (gh_pair_p (cursor_))
149 Music *m =unsmob_music (ly_car (cursor_));
150 iter_ = unsmob_iterator (get_iterator (m));
153 while (iter_ && !iter_->ok ())
158 here_mom_ = get_music ()->start_mom ();
159 grace_fixups_ = get_grace_fixups (cursor_);
162 iter_->ok () is tautology, but what the heck.
164 if (iter_ && iter_->ok ())
170 maintain invariants: change cursor, iter and here_mom_ in one fell
174 Sequential_iterator::next_element (bool side_effect)
176 Moment len =iter_->music_length_mom () - iter_->music_start_mom ();
177 assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_);
179 if (len.main_part_ && grace_fixups_ &&
180 grace_fixups_->start_ == here_mom_)
182 here_mom_ += grace_fixups_->length_;
183 here_mom_.grace_part_ += grace_fixups_->grace_start_;
185 Grace_fixup * n =grace_fixups_->next_;
186 delete grace_fixups_;
189 else if (len.grace_part_ && !len.main_part_)
191 here_mom_.grace_part_ =0;
196 !len.grace_part_ || len.main_part_
198 We skip over a big chunk (mainpart != 0). Any starting graces
199 in that chunk should be in len.grace_part_
205 cursor_ = ly_cdr (cursor_);
208 if (gh_pair_p (cursor_))
209 iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
215 move to context of child iterator if it is deeper down in the
219 Sequential_iterator::descend_to_child ()
225 Retrieve all music (starting at HERE), until a music with length L >
226 0 is found. From the precondition, we know that UNTIL is later than
227 the earliest event. Hence we know
231 so something that comes after this thing with L > 0 happens after
233 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
235 Hence all events after the one with L>0 are uninteresting, so we
241 Sequential_iterator::get_pending_events (Moment until)const
244 if (until < pending_moment ())
247 Sequential_iterator * me =
248 dynamic_cast<Sequential_iterator*> (clone ());
251 SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
252 s = gh_append2 (nm, s);
255 for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
257 Music *mus=unsmob_music (ly_car (i));
258 m = m >? (mus->length_mom () - mus->start_mom ());
263 me->next_element (false);
266 scm_gc_unprotect_object (me->self_scm());
272 Skip events till UNTIL. We don't do any other side effects such as
273 descending to child iterator contexts, because they might depend on
274 \context specs and \translator changes being executed
277 Sequential_iterator::skip (Moment until)
282 grace_fixups_->start_ == here_mom_
283 && (grace_fixups_->start_ + grace_fixups_->length_
284 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
287 do the stuff/note/rest preceding a grace.
289 iter_->skip (iter_->music_length_mom ());
291 else if (iter_->music_length_mom () >= until - here_mom_)
292 iter_->skip (until - here_mom_ + iter_->music_start_mom ());
297 next_element (false);
302 Sequential_iterator::process (Moment until)
307 grace_fixups_->start_ == here_mom_
308 && (grace_fixups_->start_ + grace_fixups_->length_
309 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
312 do the stuff/note/rest preceding a grace.
314 iter_->process (iter_->music_length_mom ());
317 iter_->process (until - here_mom_ + iter_->music_start_mom ());
320 if the iter is still OK, there must be events left that have
334 Sequential_iterator::pending_moment () const
336 Moment cp = iter_->pending_moment ();
339 Fix-up a grace note halfway in the music.
341 if (grace_fixups_ && here_mom_ == grace_fixups_->start_
342 && grace_fixups_->length_ + iter_->music_start_mom () == cp)
344 return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
348 Fix-up a grace note at the start of the music.
350 return cp + here_mom_ - iter_->music_start_mom ();
355 Sequential_iterator::ok () const
361 Sequential_iterator::try_music_in_children (Music *m) const
363 return iter_ ? iter_->try_music (m) : 0;
366 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);