lilypond-1.3.154
[lilypond.git] / lily / sequential-music-iterator.cc
blobad1ae7b934d41bf2dd83018001779bcb6a95aef1
1 /*
2 Sequential_music_iterator.cc -- implement Sequential_music_iterator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include "grace-iterator.hh"
9 #include "translator-group.hh"
10 #include "debug.hh"
11 #include "sequential-music-iterator.hh"
12 #include "music-list.hh"
13 #include "request-chord-iterator.hh"
16 Invariant for the data structure.
19 if (gh_pair_p (cursor_))
20 iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
21 else
22 iter_p_ == 0;
24 The length of musiclist from start to up to cursor_ (cursor_ not
25 including), is summed
27 here_mom_ = sum (length (musiclist [start ... cursor>)) %)
32 Sequential_music_iterator::Sequential_music_iterator ()
34 cursor_ = SCM_EOL;
35 here_mom_ = Moment (0);
37 iter_p_ =0;
40 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
41 : Music_iterator (src)
43 cursor_ = src.cursor_;
44 here_mom_ = src.here_mom_;
45 if (src.iter_p_)
46 iter_p_ = src.iter_p_->clone ();
47 else
48 iter_p_ = 0;
51 Sequential_music_iterator::~Sequential_music_iterator ()
53 delete iter_p_;
56 void
57 Sequential_music_iterator::construct_children ()
59 cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
61 iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
62 while (iter_p_ && !iter_p_->ok ())
64 next_element ();
68 iter_p_->ok () is tautology, but what the heck.
70 if (iter_p_ && iter_p_->ok ())
71 descend_to_child ();
77 maintain invariants: change cursor, iter and here_mom_ in one fell
78 swoop.
80 void
81 Sequential_music_iterator::next_element ()
83 here_mom_ += iter_p_->music_length_mom ();
84 delete iter_p_;
85 cursor_ = gh_cdr (cursor_);
87 if (gh_pair_p (cursor_))
88 iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
89 else
90 iter_p_ = 0;
94 move to context of child iterator if it is deeper down in the
95 hierarchy.
98 void
99 Sequential_music_iterator::descend_to_child ()
101 Translator_group * child_report = child_report = iter_p_->report_to_l ();
102 Translator_group * me_report = report_to_l ();
104 if (dynamic_cast<Grace_iterator*> (iter_p_))
105 child_report = child_report->daddy_trans_l_;
107 Translator_group * c = child_report;
108 while (c && c != me_report)
110 c= c->daddy_trans_l_;
113 if (c == me_report)
114 set_translator (child_report);
119 Retrieve all music (starting at HERE), until a music with length L >
120 0 is found. From the precondition, we know that UNTIL is later than
121 the earliest event. Hence we know
123 L >= (UNTIL - HERE)
125 so something that comes after this thing with L > 0 happens after
127 HERE + L >= HERE + (UNTIL - HERE) = UNTIL
129 Hence all events after the one with L>0 are uninteresting, so we
130 ignore them.
135 Sequential_music_iterator::get_music (Moment until)const
137 SCM s = SCM_EOL;
138 if (until < pending_moment ())
139 return s;
141 Sequential_music_iterator * me =
142 dynamic_cast<Sequential_music_iterator*> (clone ());
143 while (me->ok ())
145 SCM nm = me->iter_p_->get_music (until - me->here_mom_);
146 s = gh_append2 (nm, s);
148 Moment m = 0;
149 for (SCM i = nm; gh_pair_p (i); i = gh_cdr (i))
150 m = m >? unsmob_music (gh_car (i))->length_mom ();
152 if (m > Moment (0))
153 break ;
154 else
155 me->next_element ();
157 delete me;
159 return s;
162 Skip events till UNTIL. We don't do any other side effects (such as
163 moving descending to child iterator contexts, because they might
164 depend on \context specs and \translator changes being executed
167 void
168 Sequential_music_iterator::skip (Moment until)
170 while (ok ())
172 Moment l =iter_p_->music_length_mom ();
173 if (l >= until - here_mom_)
174 iter_p_->skip (until - here_mom_);
176 if (iter_p_->ok ())
177 return ;
179 next_element ();
183 void
184 Sequential_music_iterator::process (Moment until)
186 while (iter_p_)
188 iter_p_->process (until - here_mom_);
191 if the iter is still OK, there must be events left that have
193 TIME > LEFT
196 if (iter_p_->ok ())
197 return ;
199 descend_to_child ();
200 next_element ();
204 Moment
205 Sequential_music_iterator::pending_moment () const
207 return iter_p_->pending_moment () + here_mom_;
211 bool
212 Sequential_music_iterator::ok () const
214 return iter_p_;
217 Music_iterator*
218 Sequential_music_iterator::try_music_in_children (Music *m) const
220 return iter_p_ ? iter_p_->try_music (m) : 0;
222 IMPLEMENT_CTOR_CALLBACK (Sequential_music_iterator);