2 Sequential_iterator.cc -- implement Sequential_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2004 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 *get_grace_fixups (SCM cursor);
18 TODO: handling of grace notes is exquisite pain. This handling
19 should be formally specified and then the implementation verified.
24 Invariant for the data structure.
27 if (gh_pair_p (cursor_))
28 iter_->music_ == unsmob_music (ly_car (cursor_))
32 The length of musiclist from start to up to cursor_ (cursor_ not
35 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
38 Sequential_iterator::Sequential_iterator ()
40 here_mom_ = Moment (0);
48 Sequential_iterator::get_music_list () const
54 Sequential_iterator::do_quit ()
64 Sequential_iterator::derived_mark ()const
67 scm_gc_mark (iter_->self_scm ());
69 scm_gc_mark (cursor_);
74 Sequential_iterator::derived_substitute (Context *f,Context *t)
77 iter_->substitute_outlet (f,t);
82 create_grace_fixup_list (SCM cursor)
86 Grace_fixup *head = 0;
87 Grace_fixup **tail = &head;
89 for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
91 Music *mus = unsmob_music (ly_car (cursor));
92 Moment s = mus->start_mom ();
93 Moment l = mus->get_length () - s;
97 if (last != Moment (-1))
99 Grace_fixup *p = new Grace_fixup;
101 p->length_ = here - last;
102 p->grace_start_ = s.grace_part_;
105 tail = &(*tail)->next_;
108 here.grace_part_ = s.grace_part_;
122 Sequential_iterator::construct_children ()
124 list_ = get_music_list ();
128 if (gh_pair_p (cursor_))
130 Music *m =unsmob_music (ly_car (cursor_));
131 iter_ = unsmob_iterator (get_iterator (m));
134 while (iter_ && !iter_->ok ())
139 here_mom_ = get_music ()->start_mom ();
140 grace_fixups_ = create_grace_fixup_list (cursor_);
143 iter_->ok () is tautology, but what the heck.
145 if (iter_ && iter_->ok ())
151 maintain invariants: change cursor, iter and here_mom_ in one fell
155 Sequential_iterator::next_element (bool)
157 Moment len =iter_->music_get_length () - iter_->music_start_mom ();
158 assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_);
161 && get_grace_fixup ())
163 Grace_fixup *gf = get_grace_fixup ();
165 here_mom_ += gf->length_;
166 here_mom_.grace_part_ += gf->grace_start_;
170 else if (len.grace_part_ && !len.main_part_)
172 here_mom_.grace_part_ =0;
177 !len.grace_part_ || len.main_part_
179 We skip over a big chunk (mainpart != 0). Any starting graces
180 in that chunk should be in len.grace_part_
186 cursor_ = ly_cdr (cursor_);
189 if (gh_pair_p (cursor_))
190 iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
196 move to context of child iterator if it is deeper down in the
200 Sequential_iterator::descend_to_child ()
202 Context * child_report = child_report = iter_->get_outlet ();
203 Context * me_report = get_outlet ();
205 Context * c = child_report;
206 while (c && c != me_report)
208 c = c->daddy_context_;
212 set_translator (child_report);
218 Sequential_iterator::process (Moment until)
222 Grace_fixup * gf = get_grace_fixup ();
224 && gf->start_ + gf->length_
225 + Moment (Rational (0), gf->grace_start_) == until)
228 do the stuff/note/rest preceding a grace.
230 iter_->process (iter_->music_get_length ());
234 Moment w = until - here_mom_ + iter_->music_start_mom ();
239 if the iter is still OK, there must be events left that have
253 Sequential_iterator::pending_moment () const
255 Moment cp = iter_->pending_moment ();
258 Fix-up a grace note halfway in the music.
260 Grace_fixup * gf = get_grace_fixup ();
262 && gf->length_ + iter_->music_start_mom () == cp)
264 return here_mom_ + gf->length_ + Moment (0, gf->grace_start_);
268 Fix-up a grace note at the start of the music.
270 return cp + here_mom_ - iter_->music_start_mom ();
275 Sequential_iterator::ok () const
281 Sequential_iterator::try_music_in_children (Music *m) const
283 return iter_ ? iter_->try_music (m) : 0;
286 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);
289 Sequential_iterator::run_always () const
291 return iter_ ? iter_->run_always () : false;
295 Sequential_iterator::next_grace_fixup ()
297 Grace_fixup * n = grace_fixups_->next_;
298 delete grace_fixups_;
304 Sequential_iterator::get_grace_fixup () const
306 if (grace_fixups_ && grace_fixups_->start_ == here_mom_)
307 return grace_fixups_;