2 Translator_group.cc -- implement Translator_group
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "music-output-def.hh"
10 #include "translator-group.hh"
11 #include "translator.hh"
15 #include "killing-cons.tcc"
17 Translator_group::Translator_group (Translator_group
const&s
)
20 consists_str_arr_
= s
.consists_str_arr_
;
21 consists_end_str_arr_
= s
.consists_end_str_arr_
;
22 accepts_str_arr_
= s
.accepts_str_arr_
;
24 properties_dict_
= s
.properties_dict_
;
27 Translator_group::~Translator_group ()
29 assert (removable_b());
30 trans_p_list_
.junk ();
34 Translator_group::Translator_group()
40 Translator_group::check_removal()
42 Cons
<Translator
> *next
=0;
43 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= next
)
46 if (Translator_group
*trg
= dynamic_cast <Translator_group
*> (p
->car_
))
48 trg
->check_removal ();
49 if (trg
->removable_b())
50 terminate_translator (trg
);
56 Translator_group::add_translator (Translator
*trans_p
)
58 trans_p_list_
.append (new Killing_cons
<Translator
> (trans_p
,0));
60 trans_p
->daddy_trans_l_
= this;
61 trans_p
->output_def_l_
= output_def_l_
;
62 trans_p
->add_processing ();
66 Translator_group::set_acceptor (String accepts
, bool add
)
69 accepts_str_arr_
.push (accepts
);
71 for (int i
=accepts_str_arr_
.size (); i
--; )
72 if (accepts_str_arr_
[i
] == accepts
)
73 accepts_str_arr_
.del (i
);
77 Translator_group::add_last_element (String s
)
79 if (!get_translator_l (s
))
80 error (_ ("Program has no such type"));
82 for (int i
=consists_end_str_arr_
.size (); i
--; )
83 if (consists_end_str_arr_
[i
] == s
)
84 warning (_f ("Already contains: `%s'", s
));
86 consists_end_str_arr_
.push (s
);
90 Translator_group::set_element (String s
, bool add
)
92 if (!get_translator_l (s
))
93 error (_ ("Program has no such type"));
97 for (int i
=consists_str_arr_
.size (); i
--; )
98 if (consists_str_arr_
[i
] == s
)
99 warning (_f("Already contains: `%s'", s
));
101 consists_str_arr_
.push (s
);
105 for (int i
=consists_str_arr_
.size (); i
--; )
106 if (consists_str_arr_
[i
] == s
)
107 consists_str_arr_
.del (i
);
108 for (int i
=consists_end_str_arr_
.size (); i
--; )
109 if (consists_end_str_arr_
[i
] == s
)
110 consists_end_str_arr_
.del (i
);
114 Translator_group::removable_b() const
116 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
118 if (dynamic_cast <Translator_group
*> (p
->car_
))
122 return !iterator_count_
;
126 Translator_group::find_existing_translator_l (String n
, String id
)
128 if (is_alias_b (n
) && (id_str_
== id
|| id
.empty_b ()))
131 Translator_group
* r
= 0;
132 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; !r
&& p
; p
= p
->next_
)
134 if (Translator_group
*trg
= dynamic_cast <Translator_group
*> (p
->car_
))
135 r
= trg
->find_existing_translator_l (n
, id
);
141 Link_array
<Translator_group
>
142 Translator_group::path_to_acceptable_translator (String type
, Music_output_def
* odef
) const
144 Link_array
<Translator_group
> accepted_arr
;
145 for (int i
=0; i
< accepts_str_arr_
.size (); i
++)
147 Translator
*t
= odef
->find_translator_l (accepts_str_arr_
[i
]);
148 if (!t
|| !dynamic_cast <Translator_group
*> (t
))
150 accepted_arr
.push (dynamic_cast <Translator_group
*> (t
));
154 for (int i
=0; i
< accepted_arr
.size (); i
++)
155 if (accepted_arr
[i
]->type_str_
== type
)
157 Link_array
<Translator_group
> retval
;
158 retval
.push (accepted_arr
[i
]);
162 Link_array
<Translator_group
> best_result
;
163 int best_depth
= INT_MAX
;
164 for (int i
=0; i
< accepted_arr
.size (); i
++)
166 Translator_group
* g
= accepted_arr
[i
];
168 Link_array
<Translator_group
> result
169 = g
->path_to_acceptable_translator (type
, odef
);
170 if (result
.size () && result
.size () < best_depth
)
173 best_result
= result
;
181 Translator_group::find_create_translator_l (String n
, String id
)
183 Translator_group
* existing
= find_existing_translator_l (n
,id
);
187 Link_array
<Translator_group
> path
188 = path_to_acceptable_translator (n
, output_def_l ());
192 Translator_group
* current
= this;
194 // start at 1. The first one (index 0) will be us.
195 for (int i
=0; i
< path
.size (); i
++)
197 Translator_group
* new_group
= dynamic_cast<Translator_group
*>(path
[i
]->clone ());
199 current
->add_translator (new_group
);
202 current
->id_str_
= id
;
206 Translator_group
*ret
= 0;
208 ret
= daddy_trans_l_
->find_create_translator_l (n
,id
);
211 warning (_f ("can't find or create `%s' called `%s'", n
, id
));
218 Translator_group::try_music_on_nongroup_children (Music
*m
)
220 bool hebbes_b
=false;
222 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; !hebbes_b
&& p
; p
= p
->next_
)
224 if (!dynamic_cast <Translator_group
*> (p
->car_
))
226 hebbes_b
= p
->car_
->try_music (m
);
233 Translator_group::do_try_music (Music
* m
)
235 bool hebbes_b
= try_music_on_nongroup_children (m
);
237 if (!hebbes_b
&& daddy_trans_l_
)
238 hebbes_b
= daddy_trans_l_
->try_music (m
);
243 Translator_group::depth_i() const
245 return (daddy_trans_l_
) ? daddy_trans_l_
->depth_i() + 1 : 0;
249 Translator_group::ancestor_l (int level
)
251 if (!level
|| !daddy_trans_l_
)
254 return daddy_trans_l_
->ancestor_l (level
-1);
262 Translator_group::terminate_translator (Translator
*r_l
)
264 r_l
->removal_processing();
265 Translator
* trans_p
=remove_translator_p (r_l
);
272 Remove a translator from the hierarchy.
275 Translator_group::remove_translator_p (Translator
*trans_l
)
279 for (Cons
<Translator
> **pp
= &trans_p_list_
.head_
; *pp
; pp
= &(*pp
)->next_
)
280 if ((*pp
)->car_
== trans_l
)
282 Cons
<Translator
> *r
= trans_p_list_
.remove_cons (pp
);
284 trans_l
->daddy_trans_l_
=0;
294 Translator_group::get_simple_translator (String type
) const
296 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
298 if (classname (p
->car_
) == type
)
302 return daddy_trans_l_
->get_simple_translator (type
);
308 Translator_group::is_bottom_translator_b () const
310 return !accepts_str_arr_
.size ();
316 Translator_group::get_default_interpreter()
318 if (accepts_str_arr_
.size())
320 Translator
*t
= output_def_l ()->find_translator_l (accepts_str_arr_
[0]);
323 warning (_f ("can't find or create: `%s'", accepts_str_arr_
[0]));
326 Translator_group
* g
= dynamic_cast <Translator_group
*>(t
->clone ());
329 if (!g
->is_bottom_translator_b ())
330 return g
->get_default_interpreter ();
338 Translator_group::each (Method_pointer method
)
340 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
341 (p
->car_
->*method
) ();
346 Translator_group::each (Const_method_pointer method
) const
348 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
349 (p
->car_
->*method
) ();
353 Translator_group::do_print() const
359 gh_display (properties_dict_
.self_scm_
);
360 if (status
== ORPHAN
)
362 DEBUG_OUT
<< "consists of: ";
363 for (int i
=0; i
< consists_str_arr_
.size (); i
++)
364 DEBUG_OUT
<< consists_str_arr_
[i
] << ", ";
365 DEBUG_OUT
<< "\naccepts: ";
366 for (int i
=0; i
< accepts_str_arr_
.size (); i
++)
367 DEBUG_OUT
<< accepts_str_arr_
[i
] << ", ";
371 if (id_str_
.length_i ())
372 DEBUG_OUT
<< "ID: " << id_str_
;
373 DEBUG_OUT
<< " iterators: " << iterator_count_
<< '\n';
375 each (&Translator::print
);
380 Translator_group::do_pre_move_processing ()
382 each (&Translator::pre_move_processing
);
386 Translator_group::do_post_move_processing ()
388 each (&Translator::post_move_processing
);
392 Translator_group::do_process_music ()
394 each (&Translator::process_music
);
398 Translator_group::do_creation_processing ()
400 each (&Translator::creation_processing
);
404 Translator_group::do_removal_processing ()
406 each (&Translator::removal_processing
);
410 Translator_group::do_add_processing ()
412 for (int i
=0; i
< consists_str_arr_
.size(); i
++)
414 String s
= consists_str_arr_
[i
];
415 Translator
* t
= output_def_l ()->find_translator_l (s
);
417 warning (_f ("can't find: `%s'", s
));
419 add_translator (t
->clone ());
421 for (int i
=0; i
-- < consists_end_str_arr_
.size (); i
++)
423 String s
= consists_end_str_arr_
[i
];
424 Translator
* t
= output_def_l ()->find_translator_l (s
);
426 warning (_f ("can't find: `%s'", s
));
428 add_translator (t
->clone ());
433 Translator_group::where_defined (SCM sym
) const
435 if (properties_dict_
.elem_b (sym
))
437 return (Translator_group
*)this;
440 return (daddy_trans_l_
) ? daddy_trans_l_
->where_defined (sym
) : 0;
444 Translator_group::get_property (SCM sym
) const
446 if (properties_dict_
.elem_b (sym
))
448 return properties_dict_
.get (sym
);
452 return daddy_trans_l_
->get_property (sym
);
455 return SCM_UNDEFINED
;
459 Translator_group::set_property (String id
, SCM val
)
461 properties_dict_
.set (ly_symbol2scm (id
.ch_C()), val
);