Correct left text alignment of DynamicTextSpanner.
[lilypond.git] / lily / translator.cc
blobdc70c155ce97058e9491a598360ceb7f3d19012c
1 /*
2 translator.cc -- implement Translator
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
9 #include "translator.hh"
11 #include "context-def.hh"
12 #include "dispatcher.hh"
13 #include "global-context.hh"
14 #include "international.hh"
15 #include "translator-group.hh"
16 #include "warn.hh"
18 #include "translator.icc"
19 #include "ly-smobs.icc"
21 Translator::~Translator ()
25 void
26 Translator::init ()
28 must_be_last_ = false;
29 self_scm_ = SCM_EOL;
30 daddy_context_ = 0;
31 smobify_self ();
34 void
35 Translator::process_music ()
39 void
40 Translator::process_acknowledged ()
44 Translator::Translator ()
46 init ();
49 Translator::Translator (Translator const &src)
51 init ();
52 must_be_last_ = src.must_be_last_;
55 Moment
56 Translator::now_mom () const
58 return daddy_context_->now_mom ();
61 Output_def *
62 Translator::get_output_def () const
64 return daddy_context_->get_output_def ();
67 Translator_group *
68 Translator::get_daddy_translator () const
70 return daddy_context_->implementation ();
73 void
74 Translator::protect_event (SCM ev)
76 get_daddy_translator ()->protect_event (ev);
79 SCM
80 Translator::internal_get_property (SCM sym) const
82 return daddy_context_->internal_get_property (sym);
85 void
86 Translator::stop_translation_timestep ()
91 this function is called once each moment, before any user
92 information enters the translators. (i.e. no \property or event has
93 been processed yet.)
95 void
96 Translator::start_translation_timestep ()
100 void
101 Translator::initialize ()
105 void
106 Translator::finalize ()
110 void
111 Translator::connect_to_context (Context *c)
113 for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
114 c->events_below ()->add_listener (r->get_listener_ (this), r->event_class_);
117 void
118 Translator::disconnect_from_context (Context *c)
120 for (translator_listener_record *r = get_listener_list (); r; r=r->next_)
121 c->events_below ()->remove_listener (r->get_listener_ (this), r->event_class_);
124 static SCM listened_event_class_table;
125 void
126 ensure_listened_hash ()
128 if (!listened_event_class_table)
129 listened_event_class_table = scm_permanent_object (scm_c_make_hash_table (61));
133 LY_DEFINE (ly_get_listened_event_classes, "ly:get-listened-event-classes",
134 0, 0, 0, (),
135 "Return a list of all event classes that some translator listens"
136 " to.")
138 ensure_listened_hash ();
139 return ly_hash_table_keys (listened_event_class_table);
142 LY_DEFINE (ly_is_listened_event_class, "ly:is-listened-event-class",
143 1, 0, 0, (SCM sym),
144 "Is @var{sym} a listened event class?")
146 ensure_listened_hash ();
147 return scm_hashq_ref (listened_event_class_table, sym, SCM_BOOL_F);
150 void
151 add_listened_event_class (SCM sym)
153 ensure_listened_hash ();
154 scm_hashq_set_x (listened_event_class_table, sym, SCM_BOOL_T);
159 internally called once, statically, for each translator
160 listener. Connects the name of an event class with a procedure that
161 fetches the corresponding listener.
163 The method should only be called from the macro
164 IMPLEMENT_TRANSLATOR_LISTENER.
166 void
167 Translator::add_translator_listener (translator_listener_record **listener_list,
168 translator_listener_record *r,
169 Listener (*get_listener) (void *),
170 const char *ev_class)
172 /* ev_class is the C++ identifier name. Convert to scm symbol */
173 string name = string (ev_class);
174 name = replace_all (&name, '_', '-');
175 name += "-event";
177 SCM class_sym = scm_str2symbol (name.c_str ());
179 add_listened_event_class (class_sym);
181 r->event_class_ = class_sym;
182 r->get_listener_ = get_listener;
183 r->next_ = *listener_list;
184 *listener_list = r;
188 Helps the individual static_translator_description methods of translators.
191 Translator::static_translator_description (const char *grobs,
192 const char *desc,
193 translator_listener_record *listener_list,
194 const char *read,
195 const char *write) const
197 SCM static_properties = SCM_EOL;
199 static_properties = scm_acons (ly_symbol2scm ("grobs-created"),
200 parse_symbol_list (grobs), static_properties);
202 static_properties = scm_acons (ly_symbol2scm ("description"),
203 scm_from_locale_string (desc), static_properties);
205 SCM list = SCM_EOL;
206 for (; listener_list; listener_list = listener_list->next_)
207 list = scm_cons (listener_list->event_class_, list);
208 static_properties = scm_acons (ly_symbol2scm ("events-accepted"),
209 list, static_properties);
211 static_properties = scm_acons (ly_symbol2scm ("properties-read"),
212 parse_symbol_list (read), static_properties);
214 static_properties = scm_acons (ly_symbol2scm ("properties-written"),
215 parse_symbol_list (write), static_properties);
217 return static_properties;
221 SMOBS
224 Translator::mark_smob (SCM sm)
226 Translator *me = (Translator *) SCM_CELL_WORD_1 (sm);
227 me->derived_mark ();
228 return SCM_EOL;
231 Global_context *
232 Translator::get_global_context () const
234 return daddy_context_->get_global_context ();
237 Context *
238 Translator::get_score_context () const
240 return daddy_context_->get_score_context ();
243 IMPLEMENT_SMOBS (Translator);
244 IMPLEMENT_DEFAULT_EQUAL_P (Translator);
245 IMPLEMENT_TYPE_P (Translator, "ly:translator?");
247 bool
248 Translator::must_be_last () const
250 return must_be_last_;
253 void
254 Translator::derived_mark () const
259 Translator::print_smob (SCM s, SCM port, scm_print_state *)
261 Translator *me = (Translator *) SCM_CELL_WORD_1 (s);
262 scm_puts ("#<Translator ", port);
263 scm_puts (me->class_name (), port);
264 scm_puts (" >", port);
265 return 1;
268 void
269 add_acknowledger (Engraver_void_function_engraver_grob_info ptr,
270 char const *func_name,
271 vector<Acknowledge_information> *ack_array)
273 Acknowledge_information inf;
274 inf.function_ = ptr;
276 string interface_name (func_name);
278 interface_name = replace_all (&interface_name, '_', '-');
279 interface_name += "-interface";
282 this is only called during program init, so safe to use scm_gc_protect_object ()
284 inf.symbol_ = scm_gc_protect_object (ly_symbol2scm (interface_name.c_str ()));
285 ack_array->push_back (inf);
288 Engraver_void_function_engraver_grob_info
289 generic_get_acknowledger (SCM sym, vector<Acknowledge_information> const *ack_array)
291 for (vsize i = 0; i < ack_array->size (); i++)
293 if (ack_array->at (i).symbol_ == sym)
294 return ack_array->at (i).function_;
296 return 0;
300 Moment
301 get_event_length (Stream_event *e)
303 Moment *m = unsmob_moment (e->get_property ("length"));
304 if (m)
305 return *m;
306 else
307 return Moment (0);
310 Moment
311 get_event_length (Stream_event *e, Moment now)
313 Moment len = get_event_length (e);
315 if (now.grace_part_)
317 len.grace_part_ = len.main_part_;
318 len.main_part_ = Rational (0);
320 return len;
324 Helper, used through ASSIGN_EVENT_ONCE to throw warnings for
325 simultaneous events. The helper is only useful in listen_* methods
326 of translators.
328 bool
329 internal_event_assignment (Stream_event **old_ev, Stream_event *new_ev, const char *function)
331 if (*old_ev &&
332 !to_boolean (scm_equal_p ((*old_ev)->self_scm (),
333 new_ev->self_scm ())))
335 /* extract event class from function name */
336 string ev_class = function;
338 /* This assertion fails if EVENT_ASSIGNMENT was called outside a
339 translator listener. Don't do that. */
340 const char *prefix = "listen_";
341 assert (0 == ev_class.find (prefix));
343 /* "listen_foo_bar" -> "foo-bar" */
344 ev_class.erase (0, strlen (prefix));
345 replace_all (&ev_class, '_', '-');
347 new_ev->origin ()->warning (_f ("Two simultaneous %s events, junking this one", ev_class.c_str ()));
348 (*old_ev)->origin ()->warning (_f ("Previous %s event here", ev_class.c_str ()));
349 return false;
351 else
353 *old_ev = new_ev;
354 return true;
358 ADD_TRANSLATOR (Translator,
359 /* doc */
360 "Base class. Not instantiated.",
362 /* create */
365 /* read */
368 /* write */