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