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"
14 #include "scm-hash.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_
= new Scheme_hash_table (*s
.properties_dict_
);
27 Translator_group::~Translator_group ()
29 assert (removable_b());
30 trans_p_list_
.junk ();
31 scm_unprotect_object (properties_dict_
->self_scm ());
35 Translator_group::Translator_group()
38 properties_dict_
= new Scheme_hash_table
;
42 Translator_group::check_removal()
44 Cons
<Translator
> *next
=0;
45 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= next
)
48 if (Translator_group
*trg
= dynamic_cast <Translator_group
*> (p
->car_
))
50 trg
->check_removal ();
51 if (trg
->removable_b())
52 terminate_translator (trg
);
58 Translator_group::add_translator (Translator
*trans_p
)
60 trans_p_list_
.append (new Killing_cons
<Translator
> (trans_p
,0));
62 trans_p
->daddy_trans_l_
= this;
63 trans_p
->output_def_l_
= output_def_l_
;
64 trans_p
->add_processing ();
68 Translator_group::set_acceptor (String accepts
, bool add
)
71 accepts_str_arr_
.push (accepts
);
73 for (int i
=accepts_str_arr_
.size (); i
--; )
74 if (accepts_str_arr_
[i
] == accepts
)
75 accepts_str_arr_
.del (i
);
79 Translator_group::add_last_element (String s
)
81 if (!get_translator_l (s
))
82 error (_ ("Program has no such type"));
84 for (int i
=consists_end_str_arr_
.size (); i
--; )
85 if (consists_end_str_arr_
[i
] == s
)
86 warning (_f ("Already contains: `%s'", s
));
88 consists_end_str_arr_
.push (s
);
92 Translator_group::set_element (String s
, bool add
)
94 if (!get_translator_l (s
))
95 error (_ ("Program has no such type"));
99 for (int i
=consists_str_arr_
.size (); i
--; )
100 if (consists_str_arr_
[i
] == s
)
101 warning (_f("Already contains: `%s'", s
));
103 consists_str_arr_
.push (s
);
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
);
116 Translator_group::removable_b() const
118 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
120 if (dynamic_cast <Translator_group
*> (p
->car_
))
124 return !iterator_count_
;
128 Translator_group::find_existing_translator_l (String n
, String id
)
130 if (is_alias_b (n
) && (id_str_
== id
|| id
.empty_b ()))
133 Translator_group
* r
= 0;
134 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; !r
&& p
; p
= p
->next_
)
136 if (Translator_group
*trg
= dynamic_cast <Translator_group
*> (p
->car_
))
137 r
= trg
->find_existing_translator_l (n
, id
);
143 Link_array
<Translator_group
>
144 Translator_group::path_to_acceptable_translator (String type
, Music_output_def
* odef
) const
146 Link_array
<Translator_group
> accepted_arr
;
147 for (int i
=0; i
< accepts_str_arr_
.size (); i
++)
149 Translator
*t
= odef
->find_translator_l (accepts_str_arr_
[i
]);
150 if (!t
|| !dynamic_cast <Translator_group
*> (t
))
152 accepted_arr
.push (dynamic_cast <Translator_group
*> (t
));
156 for (int i
=0; i
< accepted_arr
.size (); i
++)
157 if (accepted_arr
[i
]->type_str_
== type
)
159 Link_array
<Translator_group
> retval
;
160 retval
.push (accepted_arr
[i
]);
164 Link_array
<Translator_group
> best_result
;
165 int best_depth
= INT_MAX
;
166 for (int i
=0; i
< accepted_arr
.size (); i
++)
168 Translator_group
* g
= accepted_arr
[i
];
170 Link_array
<Translator_group
> result
171 = g
->path_to_acceptable_translator (type
, odef
);
172 if (result
.size () && result
.size () < best_depth
)
175 best_result
= result
;
183 Translator_group::find_create_translator_l (String n
, String id
)
185 Translator_group
* existing
= find_existing_translator_l (n
,id
);
189 Link_array
<Translator_group
> path
190 = path_to_acceptable_translator (n
, output_def_l ());
194 Translator_group
* current
= this;
196 // start at 1. The first one (index 0) will be us.
197 for (int i
=0; i
< path
.size (); i
++)
199 Translator_group
* new_group
= dynamic_cast<Translator_group
*>(path
[i
]->clone ());
201 current
->add_translator (new_group
);
204 current
->id_str_
= id
;
208 Translator_group
*ret
= 0;
210 ret
= daddy_trans_l_
->find_create_translator_l (n
,id
);
213 warning (_f ("can't find or create `%s' called `%s'", n
, id
));
220 Translator_group::try_music_on_nongroup_children (Music
*m
)
222 bool hebbes_b
=false;
224 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; !hebbes_b
&& p
; p
= p
->next_
)
226 if (!dynamic_cast <Translator_group
*> (p
->car_
))
228 hebbes_b
= p
->car_
->try_music (m
);
235 Translator_group::do_try_music (Music
* m
)
237 bool hebbes_b
= try_music_on_nongroup_children (m
);
239 if (!hebbes_b
&& daddy_trans_l_
)
240 hebbes_b
= daddy_trans_l_
->try_music (m
);
245 Translator_group::depth_i() const
247 return (daddy_trans_l_
) ? daddy_trans_l_
->depth_i() + 1 : 0;
251 Translator_group::ancestor_l (int level
)
253 if (!level
|| !daddy_trans_l_
)
256 return daddy_trans_l_
->ancestor_l (level
-1);
264 Translator_group::terminate_translator (Translator
*r_l
)
266 r_l
->removal_processing();
267 Translator
* trans_p
=remove_translator_p (r_l
);
274 Remove a translator from the hierarchy.
277 Translator_group::remove_translator_p (Translator
*trans_l
)
281 for (Cons
<Translator
> **pp
= &trans_p_list_
.head_
; *pp
; pp
= &(*pp
)->next_
)
282 if ((*pp
)->car_
== trans_l
)
284 Cons
<Translator
> *r
= trans_p_list_
.remove_cons (pp
);
286 trans_l
->daddy_trans_l_
=0;
296 Translator_group::get_simple_translator (String type
) const
298 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
300 if (classname (p
->car_
) == type
)
304 return daddy_trans_l_
->get_simple_translator (type
);
310 Translator_group::is_bottom_translator_b () const
312 return !accepts_str_arr_
.size ();
318 Translator_group::get_default_interpreter()
320 if (accepts_str_arr_
.size())
322 Translator
*t
= output_def_l ()->find_translator_l (accepts_str_arr_
[0]);
325 warning (_f ("can't find or create: `%s'", accepts_str_arr_
[0]));
328 Translator_group
* g
= dynamic_cast <Translator_group
*>(t
->clone ());
331 if (!g
->is_bottom_translator_b ())
332 return g
->get_default_interpreter ();
340 Translator_group::each (Method_pointer method
)
342 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
343 (p
->car_
->*method
) ();
348 Translator_group::each (Const_method_pointer method
) const
350 for (Cons
<Translator
> *p
= trans_p_list_
.head_
; p
; p
= p
->next_
)
351 (p
->car_
->*method
) ();
355 Translator_group::do_print() const
361 gh_display (properties_dict_
->self_scm ());
362 if (status
== ORPHAN
)
364 DEBUG_OUT
<< "consists of: ";
365 for (int i
=0; i
< consists_str_arr_
.size (); i
++)
366 DEBUG_OUT
<< consists_str_arr_
[i
] << ", ";
367 DEBUG_OUT
<< "\naccepts: ";
368 for (int i
=0; i
< accepts_str_arr_
.size (); i
++)
369 DEBUG_OUT
<< accepts_str_arr_
[i
] << ", ";
373 if (id_str_
.length_i ())
374 DEBUG_OUT
<< "ID: " << id_str_
;
375 DEBUG_OUT
<< " iterators: " << iterator_count_
<< '\n';
377 each (&Translator::print
);
382 Translator_group::do_pre_move_processing ()
384 each (&Translator::pre_move_processing
);
388 Translator_group::do_post_move_processing ()
390 each (&Translator::post_move_processing
);
394 Translator_group::do_process_music ()
396 each (&Translator::process_music
);
400 Translator_group::do_creation_processing ()
402 each (&Translator::creation_processing
);
406 Translator_group::do_removal_processing ()
408 each (&Translator::removal_processing
);
412 Translator_group::do_add_processing ()
414 for (int i
=0; i
< consists_str_arr_
.size(); i
++)
416 String s
= consists_str_arr_
[i
];
417 Translator
* t
= output_def_l ()->find_translator_l (s
);
419 warning (_f ("can't find: `%s'", s
));
421 add_translator (t
->clone ());
423 for (int i
=0; i
-- < consists_end_str_arr_
.size (); i
++)
425 String s
= consists_end_str_arr_
[i
];
426 Translator
* t
= output_def_l ()->find_translator_l (s
);
428 warning (_f ("can't find: `%s'", s
));
430 add_translator (t
->clone ());
435 Translator_group::where_defined (SCM sym
) const
437 if (properties_dict_
->elem_b (sym
))
439 return (Translator_group
*)this;
442 return (daddy_trans_l_
) ? daddy_trans_l_
->where_defined (sym
) : 0;
446 Translator_group::get_property (SCM sym
) const
448 if (properties_dict_
->elem_b (sym
))
450 return properties_dict_
->get (sym
);
454 return daddy_trans_l_
->get_property (sym
);
456 return SCM_UNDEFINED
;
460 Translator_group::set_property (String id
, SCM val
)
462 set_property (ly_symbol2scm (id
.ch_C()), val
);
466 Translator_group::set_property (SCM sym
, SCM val
)
468 properties_dict_
->set (sym
, val
);