]> git.donarmstrong.com Git - lilypond.git/blob - lily/engraver-group.cc
release: 0.1.8
[lilypond.git] / lily / engraver-group.cc
1 /*
2   engravergroup.cc -- implement Engraver_group_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "proto.hh"
10 #include "plist.hh"
11 #include "engraver-group.hh"
12 #include "engraver.hh"
13 #include "debug.hh"
14 #include "p-score.hh"
15 #include "score-elem.hh"
16 #include "input-translator.hh"
17
18 Engraver* get_engraver_p (String);
19
20 void
21 Engraver_group_engraver::print()const
22
23     Engraver::print(); 
24 }
25
26 Engraver_group_engraver::~Engraver_group_engraver()
27 {
28     assert (removable_b());
29 }
30
31 void
32 Engraver_group_engraver::check_removal()
33 {
34     for (int i =0; i < group_l_arr_.size();) {
35         group_l_arr_[i]->check_removal();
36         if (group_l_arr_[i]->removable_b())
37             terminate_engraver (group_l_arr_[i]);
38         else 
39             i++;
40     }
41 }
42
43 bool
44 Engraver_group_engraver::removable_b()const
45 {
46     return !iterator_count_&& !group_l_arr_.size() ;
47 }
48
49 Engraver_group_engraver::Engraver_group_engraver()
50 {
51     itrans_l_ = 0;
52 }
53
54 void
55 Engraver_group_engraver::set_feature (Feature d)
56 {
57     PCursor<Engraver*> i (grav_list_.top());
58     // why the while construct?
59     while (i.ok()) {
60         // this construction to ensure clean deletion
61         Engraver *grav_l = i++; 
62         grav_l->set_feature (d);
63     }
64 }
65
66 void
67 Engraver_group_engraver::sync_features()
68 {
69     PCursor<Engraver*> i (grav_list_.top());
70     while (i.ok()) {
71         Engraver *grav_l = i++; 
72         grav_l->sync_features();
73     }
74 }
75
76 void
77 Engraver_group_engraver::do_pre_move_processing()
78 {
79     PCursor<Engraver*> i (grav_list_.top());
80     while (i.ok()) {
81         Engraver *grav_l = i++; 
82         grav_l->pre_move_processing();
83     }
84 }
85
86 void
87 Engraver_group_engraver::do_process_requests()
88 {
89     PCursor<Engraver*> i (grav_list_.top());
90     while (i.ok()) {
91         Engraver *grav_l = i++; 
92         grav_l->process_requests();
93     }
94 }
95
96
97 void
98 Engraver_group_engraver::do_post_move_processing()
99 {
100     PCursor<Engraver*> i (grav_list_.top());
101     while (i.ok()) {
102                 // this construction to ensure clean deletion
103         Engraver *grav_l = i++; 
104         grav_l->post_move_processing();
105     }
106 }
107
108
109 bool
110 Engraver_group_engraver::contains_b (Engraver* grav_l)const
111 {
112     bool parent_b = Engraver::contains_b (grav_l);
113     
114     if (parent_b)
115         return true;
116     for (PCursor<Engraver*> i (grav_list_.top()); i.ok (); i++)
117         if (i->contains_b (grav_l))
118             return true;
119     return false;
120 }
121         
122
123
124 bool
125 Engraver_group_engraver::do_try_request (Request*req_l)
126 {
127     bool hebbes_b =false;
128     for (int i =0; !hebbes_b && i < nongroup_l_arr_.size() ; i++)
129         hebbes_b =nongroup_l_arr_[i]->try_request (req_l);
130     if (!hebbes_b && daddy_grav_l_)
131         hebbes_b = daddy_grav_l_->try_request (req_l);
132     return hebbes_b ;
133 }
134
135 bool
136 Engraver_group_engraver::try_request (Request* r)
137 {
138     return Engraver::try_request (r);
139 }
140
141 void
142 Engraver_group_engraver::add (Engraver *grav_p)
143 {
144     grav_list_.bottom().add (grav_p);
145     grav_p->daddy_grav_l_ = this;
146
147     if (grav_p->is_type_b (Engraver_group_engraver::static_name())) {
148         group_l_arr_.push ((Engraver_group_engraver*)grav_p);
149     } else {
150         nongroup_l_arr_ .push (grav_p);
151     }
152 }
153
154
155 Engraver *
156 Engraver_group_engraver::remove_engraver_p (Engraver*grav_l)
157 {
158     group_l_arr_.substitute ((Engraver_group_engraver*)grav_l,0);
159     nongroup_l_arr_.substitute (grav_l,0);
160     PCursor<Engraver*> grav_cur (grav_list_.find (grav_l));
161     
162     return grav_cur.remove_p();
163 }
164
165 void
166 Engraver_group_engraver::terminate_engraver (Engraver*r_l)
167 {
168     DOUT << "Removing " << r_l->name() << " at " << get_staff_info ().when () << "\n";
169     r_l->removal_processing();
170     Engraver * grav_p =remove_engraver_p (r_l);
171     
172     delete grav_p;
173 }
174
175 IMPLEMENT_IS_TYPE_B2(Engraver_group_engraver,Engraver, Translator);
176
177 ADD_THIS_ENGRAVER(Engraver_group_engraver);
178
179 void
180 Engraver_group_engraver::do_print()const
181 {
182 #ifndef NPRINT
183     if ( !check_debug)
184         return ;
185     DOUT << "ID: " << id_str_ ;
186     DOUT << " iterators: " << iterator_count_<< "\n";
187     for (PCursor<Engraver*> i (grav_list_.top()); i.ok (); i++)
188         i->print();
189 #endif
190 }
191
192
193 Engraver_group_engraver*
194 Engraver_group_engraver::find_engraver_l (String n, String id)
195 {
196     if (name() == n && id_str_ == id)
197         return this;
198     Engraver_group_engraver * r = 0;
199     for (int i =0; !r && i<  group_l_arr_.size(); i++) {
200         r = group_l_arr_[i]->find_engraver_l (n,id);
201     }
202     
203     return r;
204 }
205
206 Translator*
207 Engraver_group_engraver::find_get_translator_l (String n,String id)
208 {
209     Translator * ret=0;
210     Input_translator * itrans_l= itrans_l_-> recursive_find ( n);
211     if (itrans_l) {
212         ret = find_engraver_l (n,id);
213         if (!ret) {
214             Engraver_group_engraver * group = 
215                 itrans_l-> get_group_engraver_p();
216             
217             add (group);
218             ret = group;
219             
220             if (group->itrans_l_->is_name_b (n) )
221                 ret ->id_str_ = id;
222             else
223                 return ret->find_get_translator_l (n,id);
224
225         }
226     } else if (daddy_grav_l_)
227         ret =daddy_grav_l_->find_get_translator_l (n,id);
228     else {
229         warning ("Can't find or create `" + n + "' called `" + id + "'\n");
230         ret =0;
231     }
232     return ret;
233 }
234
235 int
236 Engraver_group_engraver::depth_i()const
237 {
238     return daddy_grav_l_->depth_i()  + 1;
239 }
240
241 Translator*
242 Engraver_group_engraver::ancestor_l (int l)
243 {
244     if (!l || !daddy_grav_l_)
245         return this;
246     
247     return daddy_grav_l_->ancestor_l (l-1);
248 }
249
250 void
251 Engraver_group_engraver::announce_element (Score_elem_info info)
252 {
253     announce_info_arr_.push (info);
254     Engraver::announce_element (info);
255 }
256
257 void
258 Engraver_group_engraver::do_announces()
259 {
260     for (int i=0; i < group_l_arr_.size(); i++) {
261         group_l_arr_[i]->do_announces();
262     }
263     
264     Request dummy_req;
265  
266     for (int j =0; j < announce_info_arr_.size(); j++){
267        Score_elem_info info = announce_info_arr_[j];
268        
269        if (!info.req_l_)
270             info.req_l_ = &dummy_req;
271        for (int i=0; i < nongroup_l_arr_.size(); i++) { // Is this good enough?6
272            if (nongroup_l_arr_[i] != info.origin_grav_l_arr_[0])
273                nongroup_l_arr_[i]->acknowledge_element (info);
274        }
275     }
276     announce_info_arr_.clear();
277 }
278
279
280 void
281 Engraver_group_engraver::do_removal_processing()
282 {
283     for (PCursor<Engraver*> i (grav_list_.top()); i.ok (); i++)
284         i->removal_processing();
285 }
286
287 Staff_info
288 Engraver_group_engraver::get_staff_info()const
289 {
290     Staff_info inf = Engraver::get_staff_info();
291
292     for (int i=0; i < nongroup_l_arr_.size(); i++)
293         nongroup_l_arr_[i]->fill_staff_info (inf);
294     
295     return inf;
296 }
297
298 Translator*
299 Engraver_group_engraver::get_default_interpreter()
300 {
301     // ? 
302     if ( is_bottom_engraver_b())
303         return daddy_grav_l_->get_default_interpreter();
304
305     Engraver_group_engraver *grav_p= itrans_l_->
306         get_default_itrans_l()->get_group_engraver_p ();
307     add (grav_p);
308     if (grav_p->is_bottom_engraver_b())
309         return grav_p;
310     else
311         return grav_p->get_default_interpreter();
312 }
313
314 bool
315 Engraver_group_engraver::is_bottom_engraver_b()const
316 {
317     return !itrans_l_->get_default_itrans_l();
318 }
319
320 Engraver*
321 Engraver_group_engraver::get_simple_engraver (char const *type)const
322 {
323     for (int i=0; i < nongroup_l_arr_.size(); i++) {
324         if (nongroup_l_arr_[i]->name() == type)
325             return nongroup_l_arr_[i];
326     }
327     if ( daddy_grav_l_)
328         return daddy_grav_l_->get_simple_engraver (type);
329     return 0;
330 }
331