2 Translator_group.cc -- implement Translator_group
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2003 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 "translator-def.hh"
19 Translator_group::Translator_group (Translator_group
const&s
)
24 Scheme_hash_table
* tab
= new Scheme_hash_table (*s
.properties_dict ());
25 properties_scm_
= tab
->self_scm ();
26 scm_gc_unprotect_object (tab
->self_scm ());
30 Translator_group::properties_dict () const
32 return Scheme_hash_table::unsmob (properties_scm_
);
35 Translator_group::~Translator_group ()
38 //assert (removable_b ());
42 Translator_group::Translator_group ()
45 Scheme_hash_table
*tab
= new Scheme_hash_table
;
46 properties_scm_
= tab
->self_scm ();
48 scm_gc_unprotect_object (tab
->self_scm ());
52 Translator_group::check_removal ()
55 for (SCM p
= trans_group_list_
; gh_pair_p (p
); p
= next
)
59 Translator_group
*trg
= dynamic_cast<Translator_group
*> (unsmob_translator (ly_car (p
)));
61 trg
->check_removal ();
62 if (trg
->removable_b ())
63 terminate_translator (trg
);
68 Translator_group::add_translator (SCM list
, Translator
*t
)
71 Must append, since list ordering must be preserved.
73 list
= gh_append2 (list
, gh_cons (t
->self_scm (), SCM_EOL
));
74 t
->daddy_trans_
= this;
75 t
->output_def_
= output_def_
;
82 Translator_group::add_used_group_translator (Translator
*t
)
84 trans_group_list_
= add_translator (trans_group_list_
,t
);
89 Translator_group::add_fresh_group_translator (Translator
*t
)
91 Translator_group
*tg
= dynamic_cast<Translator_group
*> (t
);
94 trans_group_list_
= add_translator (trans_group_list_
,t
);
95 unsmob_translator_def (tg
->definition_
)->apply_property_operations (tg
);
102 Translator_group::removable_b () const
104 return trans_group_list_
== SCM_EOL
&& ! iterator_count_
;
108 Translator_group::find_existing_translator (SCM n
, String id
)
110 if ((is_alias_b (n
) && (id_string_
== id
|| id
.empty_b ())) || n
== ly_symbol2scm ("Current"))
113 Translator_group
* r
= 0;
114 for (SCM p
= trans_group_list_
; !r
&& gh_pair_p (p
); p
= ly_cdr (p
))
116 Translator
* t
= unsmob_translator (ly_car (p
));
118 r
= dynamic_cast<Translator_group
*> (t
)->find_existing_translator (n
, id
);
126 Translator_group::find_create_translator (SCM n
, String id
)
128 Translator_group
* existing
= find_existing_translator (n
,id
);
132 Link_array
<Translator_def
> path
133 = unsmob_translator_def (definition_
)->path_to_acceptable_translator (n
, get_output_def ());
137 Translator_group
* current
= this;
139 // start at 1. The first one (index 0) will be us.
140 for (int i
=0; i
< path
.size (); i
++)
142 Translator_group
* new_group
= path
[i
]->instantiate (output_def_
);
144 if (i
== path
.size () -1)
145 new_group
->id_string_
= id
;
146 current
->add_fresh_group_translator (new_group
);
153 Translator_group
*ret
= 0;
155 ret
= daddy_trans_
->find_create_translator (n
,id
);
158 warning (_f ("can't find or create `%s' called `%s'", ly_symbol2string (n
).to_str0 (), id
));
165 Translator_group::try_music (Music
* m
)
167 bool hebbes_b
= try_music_on_nongroup_children (m
);
169 if (!hebbes_b
&& daddy_trans_
)
170 hebbes_b
= daddy_trans_
->try_music (m
);
175 Translator_group::get_depth () const
177 return (daddy_trans_
) ? daddy_trans_
->get_depth () + 1 : 0;
181 Translator_group::get_ancestor (int level
)
183 if (!level
|| !daddy_trans_
)
186 return daddy_trans_
->get_ancestor (level
-1);
190 Translator_group::terminate_translator (Translator
*r
)
192 r
->removal_processing ();
194 Return value ignored. GC does the rest.
196 remove_translator (r
);
201 Remove a translator from the hierarchy.
204 Translator_group::remove_translator (Translator
*trans
)
208 trans_group_list_
= scm_delq_x (trans
->self_scm (), trans_group_list_
);
209 trans
->daddy_trans_
= 0;
214 Translator_group::is_bottom_translator_b () const
216 return !gh_symbol_p (unsmob_translator_def (definition_
)->default_child_context_name ());
220 Translator_group::get_default_interpreter ()
222 if (!is_bottom_translator_b ())
224 SCM nm
= unsmob_translator_def (definition_
)->default_child_context_name ();
225 SCM st
= get_output_def ()->find_translator (nm
);
227 Translator_def
*t
= unsmob_translator_def (st
);
230 warning (_f ("can't find or create: `%s'", ly_scm2string (nm
).to_str0 ()));
231 t
= unsmob_translator_def (this->definition_
);
233 Translator_group
*tg
= t
->instantiate (output_def_
);
234 add_fresh_group_translator (tg
);
236 if (!tg
->is_bottom_translator_b ())
237 return tg
->get_default_interpreter ();
245 static_each (SCM list
, Method_pointer method
)
247 for (SCM p
= list
; gh_pair_p (p
); p
= ly_cdr (p
))
248 (unsmob_translator (ly_car (p
))->*method
) ();
253 Translator_group::each (Method_pointer method
)
255 static_each (simple_trans_list_
, method
);
256 static_each (trans_group_list_
, method
);
264 Translator_group::where_defined (SCM sym
) const
266 if (properties_dict ()->elem_b (sym
))
268 return (Translator_group
*)this;
271 return (daddy_trans_
) ? daddy_trans_
->where_defined (sym
) : 0;
275 return SCM_EOL when not found.
278 Translator_group::internal_get_property (SCM sym
) const
281 if (properties_dict ()->try_retrieve (sym
, &val
))
285 return daddy_trans_
->internal_get_property (sym
);
291 Translator_group::internal_set_property (SCM sym
, SCM val
)
294 if (internal_type_checking_global_b
)
295 assert (type_check_assignment (sym
, val
, ly_symbol2scm ("translation-type?")));
298 properties_dict ()->set (sym
, val
);
302 TODO: look up to check whether we have inherited var?
305 Translator_group::unset_property (SCM sym
)
307 properties_dict ()->remove (sym
);
312 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
313 entry from a translator property list by name of PROP
316 Translator_group::execute_pushpop_property (SCM prop
, SCM eltprop
, SCM val
)
318 if (gh_symbol_p (prop
))
320 if (val
!= SCM_UNDEFINED
)
322 SCM prev
= internal_get_property (prop
);
324 if (gh_pair_p (prev
) || prev
== SCM_EOL
)
326 bool ok
= type_check_assignment (eltprop
, val
, ly_symbol2scm ("backend-type?"));
330 prev
= gh_cons (gh_cons (eltprop
, val
), prev
);
331 internal_set_property (prop
, prev
);
342 SCM prev
= internal_get_property (prop
);
345 TODO: should have scm_equal_something () for reverting
348 SCM newprops
= SCM_EOL
;
349 while (gh_pair_p (prev
) && ly_caar (prev
) != eltprop
)
351 newprops
= gh_cons (ly_car (prev
), newprops
);
352 prev
= ly_cdr (prev
);
355 if (gh_pair_p (prev
))
357 newprops
= scm_reverse_x (newprops
, ly_cdr (prev
));
358 internal_set_property (prop
, newprops
);
370 Translator_group::stop_translation_timestep ()
372 each (&Translator::stop_translation_timestep
);
376 Translator_group::start_translation_timestep ()
378 each (&Translator::start_translation_timestep
);
382 Translator_group::do_announces ()
384 each (&Translator::do_announces
);
388 Translator_group::initialize ()
390 SCM tab
= scm_make_vector (gh_int2scm (19), SCM_BOOL_F
);
391 set_property ("acceptHashTable", tab
);
392 each (&Translator::initialize
);
396 Translator_group::finalize ()
398 each (&Translator::removal_processing
);
403 bool translator_accepts_any_of (Translator
*tr
, SCM ifaces
)
405 SCM ack_ifs
= scm_assoc (ly_symbol2scm ("events-accepted"),
406 tr
->translator_description());
407 ack_ifs
= gh_cdr (ack_ifs
);
408 for (SCM s
= ifaces
; ly_pair_p (s
); s
= ly_cdr (s
))
409 if (scm_memq (ly_car (s
), ack_ifs
) != SCM_BOOL_F
)
415 find_accept_translators (SCM gravlist
, SCM ifaces
)
418 for (SCM s
= gravlist
; ly_pair_p (s
); s
= ly_cdr (s
))
420 Translator
* tr
= unsmob_translator (ly_car (s
));
421 if (translator_accepts_any_of (tr
, ifaces
))
422 l
= scm_cons (tr
->self_scm (), l
);
424 l
= scm_reverse_x (l
, SCM_EOL
);
430 Translator_group::try_music_on_nongroup_children (Music
*m
)
432 SCM tab
= get_property ("acceptHashTable");
433 SCM name
= scm_sloppy_assq (ly_symbol2scm ("name"),
434 m
->get_property_alist (false));
436 if (!gh_pair_p (name
))
439 name
= gh_cdr (name
);
440 SCM accept_list
= scm_hashq_ref (tab
, name
, SCM_UNDEFINED
);
441 if (accept_list
== SCM_BOOL_F
)
443 accept_list
= find_accept_translators (simple_trans_list_
,
444 m
->get_mus_property ("types"));
445 scm_hashq_set_x (tab
, name
, accept_list
);
448 for (SCM p
= accept_list
; gh_pair_p (p
); p
= ly_cdr (p
))
450 Translator
* t
= unsmob_translator (ly_car (p
));
451 if (t
&& t
->try_music (m
))
458 Translator_group::properties_as_alist () const
460 return properties_dict()->to_alist();
464 Translator_group::context_name () const
466 Translator_def
* td
= unsmob_translator_def (definition_
);
467 return ly_symbol2string (td
->type_name_
);