]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
release: 0.1.14
[lilypond.git] / lily / translator-group.cc
1 /*
2   Translator_group.cc -- implement Translator_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "music-output-def.hh"
10 #include "translator-group.hh"
11 #include "translator.hh"
12 #include "debug.hh"
13 #include "pcursor.hh"
14
15 Translator_group::Translator_group (Translator_group const&s)
16   : Translator(s)
17 {
18   consists_str_arr_ = s.consists_str_arr_;
19   accepts_str_arr_ = s.accepts_str_arr_;
20   iterator_count_ =0;
21 }
22
23 Translator_group::~Translator_group ()
24 {
25   assert (removable_b());
26 }
27
28
29 Translator_group::Translator_group()
30 {
31   iterator_count_  = 0;
32 }
33
34 void
35 Translator_group::check_removal()
36 {
37   for (int i =0; i < group_l_arr ().size();) 
38     {
39       group_l_arr ()[i]->check_removal();
40       if (group_l_arr ()[i]->removable_b())
41         terminate_translator (group_l_arr ()[i]);
42       else 
43         i++;
44     }
45 }
46
47
48
49 IMPLEMENT_IS_TYPE_B1(Translator_group, Translator);
50
51 void
52 Translator_group::add (Translator *trans_p)
53 {
54   trans_p_list_.bottom().add (trans_p);
55   trans_p->daddy_trans_l_ = this;
56   trans_p->output_def_l_ = output_def_l_;
57   trans_p->add_processing ();
58 }
59
60 bool
61 Translator_group::removable_b() const
62 {
63   return !(iterator_count_ || group_l_arr ().size());
64 }
65
66 Translator_group * 
67 Translator_group::find_existing_translator_l (String n, String id)
68 {
69   if (is_alias_b (n) && (id_str_ == id || !id)) 
70     return this;
71   Translator_group* r = 0;
72   for (int i =0; !r && i < group_l_arr ().size(); i++) 
73     {
74       r = group_l_arr ()[i]->find_existing_translator_l (n,id);
75     }
76   
77   return r;
78 }
79
80 Link_array<Translator_group>
81 Translator_group::path_to_acceptable_translator (String type) const
82 {
83   Link_array<Translator_group> retval; 
84
85   if (type_str_ == type)
86     {
87       retval.push (output_def_l ()->find_translator_l (type)->group_l ());
88     }
89   else for (int i=0; i < accepts_str_arr_.size (); i++)
90     {
91       Translator *t = output_def_l ()->find_translator_l (accepts_str_arr_[i]);
92       if (!t || !t->group_l ())
93         continue;
94       
95       Translator_group * g = t->group_l ();
96       
97       Link_array<Translator_group> result
98         = g->path_to_acceptable_translator (type);
99       if (result.size ())
100         {
101           retval.push (output_def_l ()->find_translator_l (type_str_)->group_l ());
102           retval.concat (result);
103           break;
104         }
105     }
106
107   return retval;
108 }
109
110 Translator_group*
111 Translator_group::find_create_translator_l (String n, String id)
112 {
113   Translator_group * existing = find_existing_translator_l (n,id);
114   if (existing)
115     return existing;
116   
117   Link_array<Translator_group> path = path_to_acceptable_translator (n);
118       
119   /* 
120          if path.size () == 1, then 
121          type_str_ == n, but not id == id_str_
122          */
123   if (path.size () > 1)
124     {
125       assert (path.size () > 1);
126       Translator_group * current = this;
127
128       // start at 1.  The first one (index 0) will be us.
129       for (int i=1; i < path.size (); i++) 
130         {
131           Translator_group * new_group = path[i]->clone ()->group_l ();
132           current->add (new_group);
133           current = new_group;
134         }
135       current->id_str_ = id;
136       return current;
137     }
138   
139   Translator_group *ret = 0;
140   if (daddy_trans_l_)
141     ret = daddy_trans_l_->find_create_translator_l (n,id);
142   else 
143     {
144       warning ("Can't find or create `" + n + "' called `" + id + "'\n");
145       ret =0;
146     }
147   return ret;
148 }
149
150
151 bool
152 Translator_group::do_try_request (Request* req_l)
153 {
154   bool hebbes_b =false;
155   for (int i =0; !hebbes_b && i < nongroup_l_arr ().size() ; i++)
156     hebbes_b =nongroup_l_arr ()[i]->try_request (req_l);
157   if (!hebbes_b && daddy_trans_l_)
158     hebbes_b = daddy_trans_l_->try_request (req_l);
159   return hebbes_b ;
160 }
161
162 int
163 Translator_group::depth_i() const
164 {
165   return (daddy_trans_l_) ? daddy_trans_l_->depth_i()  + 1 : 0;
166 }
167
168 Translator_group*
169 Translator_group::ancestor_l (int level)
170 {
171   if (!level || !daddy_trans_l_)
172     return this;
173   
174   return daddy_trans_l_->ancestor_l (level-1);
175 }
176
177 Link_array<Translator_group>
178 Translator_group::group_l_arr () const
179 {
180   Link_array<Translator_group> groups;
181   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
182     {
183       if (i->group_l ())
184         groups.push (i->group_l ());
185     }
186   return groups;
187 }
188
189 Link_array<Translator>
190 Translator_group::nongroup_l_arr () const
191 {
192   Link_array<Translator> groups;
193   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
194     {
195       if (!i->group_l ())
196         groups.push (i.ptr ());
197     }
198   return groups;
199 }
200
201 void
202 Translator_group::terminate_translator (Translator*r_l)
203 {
204   DOUT << "Removing " << r_l->name() << " at " << now_moment () << "\n";
205   r_l->removal_processing();
206   Translator * trans_p =remove_translator_p (r_l);
207   
208   delete trans_p;
209 }
210
211 Translator *
212 Translator_group::remove_translator_p (Translator*trans_l)
213 {
214   PCursor<Translator*> trans_cur (trans_p_list_.find (trans_l));
215   Translator * t =  trans_cur.remove_p();
216   /*
217     For elegant design, we would do this too.  Alas, it does not work yet..
218     
219     t-> removal_processing ();
220   */
221   t-> daddy_trans_l_ = 0;
222   return t;
223 }
224
225
226 Translator*
227 Translator_group::get_simple_translator (char const *type) const
228 {
229   for (int i=0; i < nongroup_l_arr ().size(); i++) 
230     {
231       if (nongroup_l_arr ()[i]->name() == type)
232         return nongroup_l_arr ()[i];
233     }
234   if (daddy_trans_l_)
235     return daddy_trans_l_->get_simple_translator (type);
236   return 0;
237 }
238
239
240 bool
241 Translator_group::is_bottom_translator_b () const
242 {
243   return !accepts_str_arr_.size ();
244 }
245
246
247
248 Translator_group*
249 Translator_group::get_default_interpreter()
250 {
251   if (accepts_str_arr_.size())
252     {
253       Translator*t = output_def_l ()->find_translator_l (accepts_str_arr_[0]);
254       Translator_group * g= t->clone ()->group_l ();
255       add (g);
256       
257       if (!g->is_bottom_translator_b ())
258         return g->get_default_interpreter ();
259       else
260         return g;
261     }
262   return this;
263 }
264
265 void
266 Translator_group::each (Method_pointer method) const
267 {
268   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
269     (i.ptr()->*method) ();     
270 }
271
272 void
273 Translator_group::do_print() const
274 {
275 #ifndef NPRINT
276   if (!check_debug)
277     return ;
278   if (status == ORPHAN)
279     {
280       DOUT << "consists of: ";
281       for (int i=0; i < consists_str_arr_.size (); i++)
282         DOUT << consists_str_arr_[i] << ", ";
283       DOUT << "\naccepts: ";
284       for (int i=0; i < accepts_str_arr_.size (); i++)
285         DOUT << accepts_str_arr_[i] << ", ";
286     }
287   else
288     {
289       if (id_str_)
290         DOUT << "ID: " << id_str_ ;
291       DOUT << " iterators: " << iterator_count_<< "\n";
292     }
293   each (&Translator::print);
294 #endif
295 }
296
297 void
298 Translator_group::do_pre_move_processing ()
299 {
300   each (&Translator::pre_move_processing);
301 }
302
303 void
304 Translator_group::do_post_move_processing ()
305 {
306   each (&Translator::post_move_processing);
307 }
308
309 void
310 Translator_group::do_process_requests ()
311 {
312   each (&Translator::process_requests);
313 }
314
315 void
316 Translator_group::do_creation_processing ()
317 {
318   each (&Translator::creation_processing);
319 }
320
321 void
322 Translator_group::do_removal_processing ()
323 {
324   each (&Translator::removal_processing);
325 }
326
327 void
328 Translator_group::do_add_processing ()
329 {
330    for (int i=0; i < consists_str_arr_.size(); i++) 
331     {
332       Translator * t = output_def_l ()->find_translator_l (consists_str_arr_[i]);
333       if (!t)
334         warning ("Could not find `" +consists_str_arr_[i]+ "'");
335       else
336         add (t->clone ());
337     }
338 }