2 Sequential_iterator.cc -- implement Sequential_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2003 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_;
73 iter_ = src.iter_->clone ();
74 scm_gc_unprotect_object (iter_->self_scm());
79 Sequential_iterator::derived_mark ()const
82 scm_gc_mark (iter_->self_scm());
84 scm_gc_mark (cursor_);
89 Sequential_iterator::derived_substitute (Translator_group*f,Translator_group*t)
92 iter_->substitute_outlet (f,t);
97 get_grace_fixups (SCM cursor)
101 Grace_fixup *head = 0;
102 Grace_fixup **tail = &head;
104 for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
106 Music * mus = unsmob_music (ly_car (cursor));
107 Moment s = mus->start_mom ();
108 Moment l =mus->get_length () - s;
112 if (last != Moment (-1))
114 Grace_fixup *p =new Grace_fixup;
116 p->length_ = here - last;
117 p->grace_start_ = s.grace_part_;
120 tail = &(*tail)->next_;
123 here.grace_part_ = s.grace_part_;
136 copy_grace_fixups (Grace_fixup* src)
138 Grace_fixup * head = 0;
139 Grace_fixup **dest = &head;
143 *dest = new Grace_fixup (*src);
144 dest = & (*dest)->next_;
152 Sequential_iterator::construct_children ()
154 list_ = get_music_list ();
158 if (gh_pair_p (cursor_))
160 Music *m =unsmob_music (ly_car (cursor_));
161 iter_ = unsmob_iterator (get_iterator (m));
164 while (iter_ && !iter_->ok ())
169 here_mom_ = get_music ()->start_mom ();
170 grace_fixups_ = get_grace_fixups (cursor_);
173 iter_->ok () is tautology, but what the heck.
175 if (iter_ && iter_->ok ())
181 maintain invariants: change cursor, iter and here_mom_ in one fell
185 Sequential_iterator::next_element (bool)
187 Moment len =iter_->music_get_length () - iter_->music_start_mom ();
188 assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_);
190 if (len.main_part_ && grace_fixups_ &&
191 grace_fixups_->start_ == here_mom_)
193 here_mom_ += grace_fixups_->length_;
194 here_mom_.grace_part_ += grace_fixups_->grace_start_;
196 Grace_fixup * n =grace_fixups_->next_;
197 delete grace_fixups_;
200 else if (len.grace_part_ && !len.main_part_)
202 here_mom_.grace_part_ =0;
207 !len.grace_part_ || len.main_part_
209 We skip over a big chunk (mainpart != 0). Any starting graces
210 in that chunk should be in len.grace_part_
216 cursor_ = ly_cdr (cursor_);
219 if (gh_pair_p (cursor_))
220 iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
226 move to context of child iterator if it is deeper down in the
230 Sequential_iterator::descend_to_child ()
232 Translator_group * child_report = child_report = iter_->report_to ();
233 Translator_group * me_report = report_to ();
235 Translator_group * c = child_report;
236 while (c && c != me_report)
242 set_translator (child_report);
247 Retrieve all music (starting at HERE), until a music with length L >
248 0 is found. From the precondition, we know that UNTIL is later than
249 the earliest event. Hence we know
253 so something that comes after this thing with L > 0 happens after
255 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
257 Hence all events after the one with L>0 are uninteresting, so we
263 Sequential_iterator::get_pending_events (Moment until) const
266 if (until < pending_moment ())
269 Sequential_iterator * me =
270 dynamic_cast<Sequential_iterator*> (clone ());
273 SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
274 s = gh_append2 (nm, s);
277 for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
279 Music *mus=unsmob_music (ly_car (i));
280 m = m >? (mus->get_length () - mus->start_mom ());
285 me->next_element (false);
288 scm_gc_unprotect_object (me->self_scm());
294 Skip events till UNTIL. We don't do any other side effects such as
295 descending to child iterator contexts, because they might depend on
296 \context specs and \translator changes being executed
299 Sequential_iterator::skip (Moment until)
304 grace_fixups_->start_ == here_mom_
305 && (grace_fixups_->start_ + grace_fixups_->length_
306 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
309 do the stuff/note/rest preceding a grace.
311 iter_->skip (iter_->music_get_length ());
313 else if (iter_->music_get_length () >= until - here_mom_)
314 iter_->skip (until - here_mom_ + iter_->music_start_mom ());
319 next_element (false);
324 Sequential_iterator::process (Moment until)
329 grace_fixups_->start_ == here_mom_
330 && (grace_fixups_->start_ + grace_fixups_->length_
331 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
334 do the stuff/note/rest preceding a grace.
336 iter_->process (iter_->music_get_length ());
339 iter_->process (until - here_mom_ + iter_->music_start_mom ());
342 if the iter is still OK, there must be events left that have
356 Sequential_iterator::pending_moment () const
358 Moment cp = iter_->pending_moment ();
361 Fix-up a grace note halfway in the music.
363 if (grace_fixups_ && here_mom_ == grace_fixups_->start_
364 && grace_fixups_->length_ + iter_->music_start_mom () == cp)
366 return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
370 Fix-up a grace note at the start of the music.
372 return cp + here_mom_ - iter_->music_start_mom ();
377 Sequential_iterator::ok () const
383 Sequential_iterator::try_music_in_children (Music *m) const
385 return iter_ ? iter_->try_music (m) : 0;
388 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);
391 Sequential_iterator::run_always () const
393 return iter_ ? iter_->run_always () : false;