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