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