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_->get_outlet ();
233 Translator_group * me_report = get_outlet ();
235 Translator_group * c = child_report;
236 while (c && c != me_report)
242 set_translator (child_report);
248 Sequential_iterator::process (Moment until)
253 grace_fixups_->start_ == here_mom_
254 && (grace_fixups_->start_ + grace_fixups_->length_
255 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
258 do the stuff/note/rest preceding a grace.
260 iter_->process (iter_->music_get_length ());
263 iter_->process (until - here_mom_ + iter_->music_start_mom ());
266 if the iter is still OK, there must be events left that have
280 Sequential_iterator::pending_moment () const
282 Moment cp = iter_->pending_moment ();
285 Fix-up a grace note halfway in the music.
287 if (grace_fixups_ && here_mom_ == grace_fixups_->start_
288 && grace_fixups_->length_ + iter_->music_start_mom () == cp)
290 return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
294 Fix-up a grace note at the start of the music.
296 return cp + here_mom_ - iter_->music_start_mom ();
301 Sequential_iterator::ok () const
307 Sequential_iterator::try_music_in_children (Music *m) const
309 return iter_ ? iter_->try_music (m) : 0;
312 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);
315 Sequential_iterator::run_always () const
317 return iter_ ? iter_->run_always () : false;