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