(process_acknowledged_grobs):
[lilypond.git] / lily / sequential-iterator.cc
blobe8812c486ea859b508e435140fd486677f947636
1 /*
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>
7 */
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_))
30 else
31 iter_ == 0;
33 The length of musiclist from start to up to cursor_ (cursor_ not
34 including), is summed
36 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
39 Sequential_iterator::Sequential_iterator ()
41 here_mom_ = Moment (0);
42 list_ = SCM_EOL;
43 cursor_ = SCM_EOL;
44 grace_fixups_ = 0;
45 iter_ =0;
48 SCM
49 Sequential_iterator::get_music_list () const
51 return SCM_EOL;
54 void
55 Sequential_iterator::do_quit ()
57 if (iter_)
58 iter_->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_;
67 list_ = src.cursor_;
68 here_mom_ = src.here_mom_;
69 iter_ = 0;
71 if (src.iter_)
73 iter_ = src.iter_->clone ();
74 scm_gc_unprotect_object (iter_->self_scm());
78 void
79 Sequential_iterator::derived_mark ()const
81 if (iter_)
82 scm_gc_mark (iter_->self_scm());
83 scm_gc_mark (list_);
84 scm_gc_mark (cursor_);
88 Grace_fixup *
89 get_grace_fixups (SCM cursor)
91 Moment here;
92 Moment last (-1);
93 Grace_fixup *head = 0;
94 Grace_fixup **tail = &head;
96 for (; gh_pair_p (cursor); cursor = ly_cdr (cursor))
98 Music * mus = unsmob_music (ly_car (cursor));
99 Moment s = mus->start_mom ();
100 Moment l =mus->get_length () - s;
102 if (s.grace_part_)
104 if (last != Moment (-1))
106 Grace_fixup *p =new Grace_fixup;
107 p->start_ = last;
108 p->length_ = here - last;
109 p->grace_start_ = s.grace_part_;
110 p->next_ = 0;
111 *tail = p;
112 tail = &(*tail)->next_;
115 here.grace_part_ = s.grace_part_;
118 if (l.to_bool())
120 last = here;
121 here += l;
124 return head;
127 Grace_fixup *
128 copy_grace_fixups (Grace_fixup* src)
130 Grace_fixup * head = 0;
131 Grace_fixup **dest = &head;
133 while (src)
135 *dest = new Grace_fixup (*src);
136 dest = & (*dest)->next_;
137 src = src ->next_;
140 return head;
143 void
144 Sequential_iterator::construct_children ()
146 list_ = get_music_list ();
147 cursor_ = list_;
149 iter_ = 0;
150 if (gh_pair_p (cursor_))
152 Music *m =unsmob_music (ly_car (cursor_));
153 iter_ = unsmob_iterator (get_iterator (m));
156 while (iter_ && !iter_->ok ())
158 next_element (true);
161 here_mom_ = get_music ()->start_mom ();
162 grace_fixups_ = get_grace_fixups (cursor_);
165 iter_->ok () is tautology, but what the heck.
167 if (iter_ && iter_->ok ())
168 descend_to_child ();
173 maintain invariants: change cursor, iter and here_mom_ in one fell
174 swoop.
176 void
177 Sequential_iterator::next_element (bool)
179 Moment len =iter_->music_get_length () - iter_->music_start_mom ();
180 assert (!grace_fixups_ || grace_fixups_->start_ >= here_mom_);
182 if (len.main_part_ && grace_fixups_ &&
183 grace_fixups_->start_ == here_mom_)
185 here_mom_ += grace_fixups_->length_;
186 here_mom_.grace_part_ += grace_fixups_->grace_start_;
188 Grace_fixup * n =grace_fixups_->next_;
189 delete grace_fixups_;
190 grace_fixups_ = n;
192 else if (len.grace_part_ && !len.main_part_)
194 here_mom_.grace_part_ =0;
196 else
199 !len.grace_part_ || len.main_part_
201 We skip over a big chunk (mainpart != 0). Any starting graces
202 in that chunk should be in len.grace_part_
205 here_mom_ += len;
208 cursor_ = ly_cdr (cursor_);
210 iter_->quit();
211 if (gh_pair_p (cursor_))
212 iter_ = unsmob_iterator (get_iterator (unsmob_music (ly_car (cursor_))));
213 else
214 iter_ = 0;
218 move to context of child iterator if it is deeper down in the
219 hierarchy.
221 void
222 Sequential_iterator::descend_to_child ()
224 Translator_group * child_report = child_report = iter_->report_to ();
225 Translator_group * me_report = report_to ();
227 Translator_group * c = child_report;
228 while (c && c != me_report)
230 c= c->daddy_trans_;
233 if (c == me_report)
234 set_translator (child_report);
239 Retrieve all music (starting at HERE), until a music with length L >
240 0 is found. From the precondition, we know that UNTIL is later than
241 the earliest event. Hence we know
243 L >= (UNTIL - HERE)
245 so something that comes after this thing with L > 0 happens after
247 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
249 Hence all events after the one with L>0 are uninteresting, so we
250 ignore them.
255 Sequential_iterator::get_pending_events (Moment until) const
257 SCM s = SCM_EOL;
258 if (until < pending_moment ())
259 return s;
261 Sequential_iterator * me =
262 dynamic_cast<Sequential_iterator*> (clone ());
263 while (me->ok ())
265 SCM nm = me->iter_->get_pending_events (until - me->here_mom_);
266 s = gh_append2 (nm, s);
268 Moment m = 0;
269 for (SCM i = nm; gh_pair_p (i); i = ly_cdr (i))
271 Music *mus=unsmob_music (ly_car (i));
272 m = m >? (mus->get_length () - mus->start_mom ());
274 if (m > Moment (0))
275 break ;
276 else
277 me->next_element (false);
280 scm_gc_unprotect_object (me->self_scm());
281 return s;
286 Skip events till UNTIL. We don't do any other side effects such as
287 descending to child iterator contexts, because they might depend on
288 \context specs and \translator changes being executed
290 void
291 Sequential_iterator::skip (Moment until)
293 while (ok ())
295 if (grace_fixups_ &&
296 grace_fixups_->start_ == here_mom_
297 && (grace_fixups_->start_ + grace_fixups_->length_
298 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
301 do the stuff/note/rest preceding a grace.
303 iter_->skip (iter_->music_get_length ());
305 else if (iter_->music_get_length () >= until - here_mom_)
306 iter_->skip (until - here_mom_ + iter_->music_start_mom ());
308 if (iter_->ok ())
309 return ;
311 next_element (false);
315 void
316 Sequential_iterator::process (Moment until)
318 while (iter_)
320 if (grace_fixups_ &&
321 grace_fixups_->start_ == here_mom_
322 && (grace_fixups_->start_ + grace_fixups_->length_
323 + Moment (Rational (0), grace_fixups_->grace_start_) == until))
326 do the stuff/note/rest preceding a grace.
328 iter_->process (iter_->music_get_length ());
330 else
331 iter_->process (until - here_mom_ + iter_->music_start_mom ());
334 if the iter is still OK, there must be events left that have
336 TIME > LEFT
339 if (iter_->ok ())
340 return ;
342 descend_to_child ();
343 next_element (true);
347 Moment
348 Sequential_iterator::pending_moment () const
350 Moment cp = iter_->pending_moment ();
353 Fix-up a grace note halfway in the music.
355 if (grace_fixups_ && here_mom_ == grace_fixups_->start_
356 && grace_fixups_->length_ + iter_->music_start_mom () == cp)
358 return here_mom_ + grace_fixups_->length_ + Moment (0, grace_fixups_->grace_start_);
362 Fix-up a grace note at the start of the music.
364 return cp + here_mom_ - iter_->music_start_mom ();
368 bool
369 Sequential_iterator::ok () const
371 return iter_;
374 Music_iterator*
375 Sequential_iterator::try_music_in_children (Music *m) const
377 return iter_ ? iter_->try_music (m) : 0;
380 IMPLEMENT_CTOR_CALLBACK (Sequential_iterator);