]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
8918a4854394371100c68f1be1f20d4dad425914
[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.empty_b ()))
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> accepted_arr;
84   for (int i=0; i < accepts_str_arr_.size (); i++)
85     {
86       Translator *t = output_def_l ()->find_translator_l (accepts_str_arr_[i]);
87       if (!t || !t->group_l ())
88         continue;
89       accepted_arr.push (t->group_l());
90     }
91
92
93  for (int i=0; i < accepted_arr.size (); i++)
94     if (accepted_arr[i]->type_str_ == type)
95       {
96         Link_array<Translator_group> retval;
97         retval.push (accepted_arr[i]);
98         return retval;
99       }
100
101   Link_array<Translator_group> best_result;
102   int best_depth= INT_MAX;
103   for (int i=0; i < accepted_arr.size (); i++)
104     {
105       Translator_group * g = accepted_arr[i];
106
107       Link_array<Translator_group> result
108         = g->path_to_acceptable_translator (type);
109       if (result.size () && result.size () < best_depth)
110         {
111           result.insert (g,0);
112           best_result = result;
113         }
114     }
115
116   return best_result;
117 }
118
119 Translator_group*
120 Translator_group::find_create_translator_l (String n, String id)
121 {
122   Translator_group * existing = find_existing_translator_l (n,id);
123   if (existing)
124     return existing;
125
126   Link_array<Translator_group> path = path_to_acceptable_translator (n);
127
128   if (path.size ())
129     {
130       Translator_group * current = this;
131
132       // start at 1.  The first one (index 0) will be us.
133       for (int i=0; i < path.size (); i++)
134         {
135           Translator_group * new_group = path[i]->clone ()->group_l ();
136           current->add (new_group);
137           current = new_group;
138         }
139       current->id_str_ = id;
140       return current;
141     }
142
143   Translator_group *ret = 0;
144   if (daddy_trans_l_)
145     ret = daddy_trans_l_->find_create_translator_l (n,id);
146   else
147     {
148       warning (_("Can't find or create `") + n + _("' called `") + id + "'\n");
149       ret =0;
150     }
151   return ret;
152 }
153
154
155 bool
156 Translator_group::do_try_request (Request* req_l)
157 {
158   bool hebbes_b =false;
159   for (int i =0; !hebbes_b && i < nongroup_l_arr ().size() ; i++)
160     hebbes_b =nongroup_l_arr ()[i]->try_request (req_l);
161   if (!hebbes_b && daddy_trans_l_)
162     hebbes_b = daddy_trans_l_->try_request (req_l);
163   return hebbes_b ;
164 }
165
166 int
167 Translator_group::depth_i() const
168 {
169   return (daddy_trans_l_) ? daddy_trans_l_->depth_i()  + 1 : 0;
170 }
171
172 Translator_group*
173 Translator_group::ancestor_l (int level)
174 {
175   if (!level || !daddy_trans_l_)
176     return this;
177
178   return daddy_trans_l_->ancestor_l (level-1);
179 }
180
181 Link_array<Translator_group>
182 Translator_group::group_l_arr () const
183 {
184   Link_array<Translator_group> groups;
185   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
186     {
187       if (i->group_l ())
188         groups.push (i->group_l ());
189     }
190   return groups;
191 }
192
193 Link_array<Translator>
194 Translator_group::nongroup_l_arr () const
195 {
196   Link_array<Translator> groups;
197   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
198     {
199       if (!i->group_l ())
200         groups.push (i.ptr ());
201     }
202   return groups;
203 }
204
205 void
206 Translator_group::terminate_translator (Translator*r_l)
207 {
208   DOUT << "Removing " << r_l->name() << " at " << now_moment () << "\n";
209   r_l->removal_processing();
210   Translator * trans_p =remove_translator_p (r_l);
211
212   delete trans_p;
213 }
214
215 Translator *
216 Translator_group::remove_translator_p (Translator*trans_l)
217 {
218   assert (trans_l);
219   
220   PCursor<Translator*> trans_cur (trans_p_list_.find (trans_l));
221   Translator * t =  trans_cur.remove_p();
222   /*
223     For elegant design, we would do this too.  Alas, it does not work yet..
224
225     t-> removal_processing ();
226   */
227   t-> daddy_trans_l_ = 0;
228   return t;
229 }
230
231
232 Translator*
233 Translator_group::get_simple_translator (char const *type) const
234 {
235   for (int i=0; i < nongroup_l_arr ().size(); i++)
236     {
237       if (nongroup_l_arr ()[i]->name() == type)
238         return nongroup_l_arr ()[i];
239     }
240   if (daddy_trans_l_)
241     return daddy_trans_l_->get_simple_translator (type);
242   return 0;
243 }
244
245
246 bool
247 Translator_group::is_bottom_translator_b () const
248 {
249   return !accepts_str_arr_.size ();
250 }
251
252
253
254 Translator_group*
255 Translator_group::get_default_interpreter()
256 {
257   if (accepts_str_arr_.size())
258     {
259       Translator*t = output_def_l ()->find_translator_l (accepts_str_arr_[0]);
260       Translator_group * g= t->clone ()->group_l ();
261       add (g);
262
263       if (!g->is_bottom_translator_b ())
264         return g->get_default_interpreter ();
265       else
266         return g;
267     }
268   return this;
269 }
270
271 void
272 Translator_group::each (Method_pointer method)
273 {
274   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
275     (i.ptr()->*method) ();
276 }
277
278 void
279 Translator_group::each (Const_method_pointer method) const
280 {
281   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
282     (i.ptr()->*method) ();
283 }
284
285 void
286 Translator_group::do_print() const
287 {
288 #ifndef NPRINT
289   if (!check_debug)
290     return ;
291   if (status == ORPHAN)
292     {
293       DOUT << "consists of: ";
294       for (int i=0; i < consists_str_arr_.size (); i++)
295         DOUT << consists_str_arr_[i] << ", ";
296       DOUT << "\naccepts: ";
297       for (int i=0; i < accepts_str_arr_.size (); i++)
298         DOUT << accepts_str_arr_[i] << ", ";
299     }
300   else
301     {
302       if (id_str_.length_i ())
303         DOUT << "ID: " << id_str_ ;
304       DOUT << " iterators: " << iterator_count_<< "\n";
305     }
306   each (&Translator::print);
307 #endif
308 }
309
310 void
311 Translator_group::do_pre_move_processing ()
312 {
313   each (&Translator::pre_move_processing);
314 }
315
316 void
317 Translator_group::do_post_move_processing ()
318 {
319   each (&Translator::post_move_processing);
320 }
321
322 void
323 Translator_group::do_process_requests ()
324 {
325   each (&Translator::process_requests);
326 }
327
328 void
329 Translator_group::do_creation_processing ()
330 {
331   each (&Translator::creation_processing);
332 }
333
334 void
335 Translator_group::do_removal_processing ()
336 {
337   each (&Translator::removal_processing);
338 }
339
340 void
341 Translator_group::do_add_processing ()
342 {
343    for (int i=0; i < consists_str_arr_.size(); i++)
344     {
345       Translator * t = output_def_l ()->find_translator_l (consists_str_arr_[i]);
346       if (!t)
347         warning (_("Could not find `") +consists_str_arr_[i]+ "'");
348       else
349         add (t->clone ());
350     }
351 }