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