]> git.donarmstrong.com Git - lilypond.git/blob - lily/sequential-music-iterator.cc
release: 1.3.92
[lilypond.git] / lily / sequential-music-iterator.cc
1 /*
2   Sequential_music_iterator.cc -- implement Sequential_music_iterator
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2000 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"
14
15 /*
16   Invariant for the data structure.
17
18
19   if (gh_pair_p (cursor_))
20     iter_p_->music_l_ == unsmob_music (gh_car (cursor_))
21   else
22     iter_p_ == 0;
23
24   The length of musiclist from start to up to cursor_ (cursor_ not
25   including), is summed
26
27   here_mom_  = sum (length (musiclist [start ... cursor> ))  %)  
28   
29  */
30
31
32 Sequential_music_iterator::Sequential_music_iterator ()
33 {
34   cursor_ = SCM_EOL;
35   here_mom_ = Moment (0);
36
37   iter_p_ =0;
38 }
39
40 Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator const &src)
41   : Music_iterator (src)
42 {
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;
49 }
50
51 Sequential_music_iterator::~Sequential_music_iterator()
52 {
53   delete iter_p_;
54 }
55
56 void
57 Sequential_music_iterator::construct_children()
58 {
59   cursor_ = dynamic_cast<Music_sequence const*> (music_l_)->music_list ();
60
61   iter_p_ = gh_pair_p (cursor_) ?  get_iterator_p (unsmob_music (gh_car (cursor_))) : 0;
62   while (iter_p_ && !iter_p_->ok ())
63     {
64       next_element ();
65     }
66
67   /*
68     iter_p_->ok () is tautology, but what the heck.
69    */
70   if (iter_p_ && iter_p_->ok()) 
71     descend_to_child ();
72
73 }
74
75
76 /*
77   maintain invariants: change cursor, iter and here_mom_ in one fell
78   swoop.
79 */
80 void
81 Sequential_music_iterator::next_element ()
82 {
83   here_mom_ += iter_p_->music_length_mom ();
84   delete iter_p_;
85   cursor_ = gh_cdr (cursor_);
86
87   if (gh_pair_p (cursor_))
88     iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_)));
89   else
90     iter_p_ = 0;
91 }
92
93 /*
94   move to context of child iterator if it is deeper down in the
95   hierarchy.
96   */
97
98 void
99 Sequential_music_iterator::descend_to_child ()
100 {
101   Translator_group  * child_report = child_report = iter_p_->report_to_l ();
102   if (dynamic_cast<Grace_iterator*> (iter_p_))
103     child_report = child_report->daddy_trans_l_;
104     
105   if (report_to_l()->depth_i () < child_report->depth_i ())
106     set_translator (child_report);
107 }
108
109
110 /*
111   Retrieve all music (starting at HERE), until a music with length L >
112   0 is found.  From the precondition, we know that UNTIL is later than
113   the earliest event. Hence we know
114   
115   L >= (UNTIL - HERE)
116
117   so something that comes after this thing with L > 0 happens after
118
119   HERE + L >= HERE + (UNTIL - HERE) = UNTIL
120
121   Hence all events after the one with L>0 are uninteresting, so we
122   ignore them.
123   
124 */
125
126 SCM
127 Sequential_music_iterator::get_music (Moment until)const
128 {
129   SCM s = SCM_EOL;
130   if (until <  pending_moment ())
131     return s;
132
133   Sequential_music_iterator * me =
134     dynamic_cast<Sequential_music_iterator*> (clone ());
135   while (me->ok ())
136     {
137       SCM nm = me->iter_p_->get_music (until - me->here_mom_);
138       s = gh_append2 (nm, s);
139       
140       Moment m = 0;
141       for (SCM i = nm; gh_pair_p(i); i = gh_cdr (i))
142         m = m >? unsmob_music (gh_car (i))->length_mom ();
143
144       if (m > Moment (0))
145         break ;
146       else
147         me->next_element ();
148     }
149   delete me;
150   
151   return s;
152 }
153 /*
154   Skip events till UNTIL. We don't do any other side effects (such as
155   moving descending to child iterator contexts, because they might
156   depend on \context specs and \translator changes being executed
157     
158  */
159 void
160 Sequential_music_iterator::skip (Moment until)
161 {
162   while (ok ())
163     {
164       Moment l =iter_p_->music_length_mom ();
165       if (l >= until - here_mom_)
166         iter_p_->skip (until - here_mom_);
167
168       if (iter_p_->ok ())
169         return ; 
170
171       next_element ();
172     }
173 }
174
175 void
176 Sequential_music_iterator::process (Moment until)
177 {
178   while (iter_p_)
179     {
180       iter_p_->process (until - here_mom_);
181
182       /*
183         if the iter is still OK, there must be events left that have
184         
185           TIME > LEFT
186           
187       */
188       if (iter_p_->ok ())
189         return ;
190
191       descend_to_child ();
192       next_element ();
193     }
194 }
195
196 Moment
197 Sequential_music_iterator::pending_moment() const
198 {
199   return iter_p_->pending_moment() + here_mom_;
200 }
201
202
203 bool
204 Sequential_music_iterator::ok() const
205 {
206   return iter_p_;
207 }
208
209 Music_iterator*
210 Sequential_music_iterator::try_music_in_children (Music *m) const
211
212   return iter_p_ ? iter_p_->try_music (m) : 0;
213 }