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