From: David Kastrup Date: Tue, 15 Sep 2015 18:50:13 +0000 (+0200) Subject: Issue 4609/4: Move \once action from iterators to listeners X-Git-Tag: release/2.19.28-1~5^2~8^2~3 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=314743a9769d8094d23cd45eb307b1485b41cb44;p=lilypond.git Issue 4609/4: Move \once action from iterators to listeners This ends the dependency of the events generated for \once\unset and \once\set on the current context (bad for recording and replaying events like with the part combiner and quoted music). It also implements \once\revert and makes every \once\override and \once\revert impervious to any other overrides and reverts that may happen at the same time. --- diff --git a/lily/context.cc b/lily/context.cc index 7e3c646a6f..ef6fecf4b1 100644 --- a/lily/context.cc +++ b/lily/context.cc @@ -252,7 +252,25 @@ Context::set_property_from_event (SCM sev) ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?")); if (ok) - set_property (sym, val); + { + if (to_boolean (ev->get_property ("once"))) + { + if (Global_context *g = get_global_context ()) + { + SCM old_val = SCM_UNDEFINED; + if (here_defined (sym, &old_val)) + g->add_finalization (scm_list_4 (ly_context_set_property_x_proc, + self_scm (), + sym, + old_val)); + else + g->add_finalization (scm_list_3 (ly_context_unset_property_proc, + self_scm (), + sym)); + } + } + set_property (sym, val); + } } } @@ -262,8 +280,28 @@ Context::unset_property_from_event (SCM sev) Stream_event *ev = unsmob (sev); SCM sym = ev->get_property ("symbol"); - type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?")); - unset_property (sym); + bool ok = type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?")); + + if (ok) + { + if (to_boolean (ev->get_property ("once"))) + { + if (Global_context *g = get_global_context ()) + { + SCM old_val = SCM_UNDEFINED; + if (here_defined (sym, &old_val)) + g->add_finalization (scm_list_4 (ly_context_set_property_x_proc, + self_scm (), + sym, + old_val)); + else + g->add_finalization (scm_list_3 (ly_context_unset_property_proc, + self_scm (), + sym)); + } + } + unset_property (sym); + } } /* diff --git a/lily/engraver-group.cc b/lily/engraver-group.cc index c69b974a69..cf1832fe1f 100644 --- a/lily/engraver-group.cc +++ b/lily/engraver-group.cc @@ -20,6 +20,7 @@ #include "context.hh" #include "dispatcher.hh" #include "engraver-group.hh" +#include "global-context.hh" #include "grob.hh" #include "grob-properties.hh" #include "paper-score.hh" @@ -30,19 +31,48 @@ void Engraver_group::override (SCM sev) { Stream_event *ev = unsmob (sev); + SCM sym = ev->get_property ("symbol"); + Grob_property_info gpi (context (), sym); - Grob_property_info (context (), ev->get_property ("symbol")) - .push (ev->get_property ("property-path"), - ev->get_property ("value")); + if (to_boolean (ev->get_property ("once"))) + { + SCM token = gpi.temporary_override (ev->get_property ("property-path"), + ev->get_property ("value")); + if (scm_is_pair (token)) + if (Global_context *g = context ()->get_global_context ()) + { + g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc, + context ()->self_scm (), + sym, + token)); + } + } + else + gpi.push (ev->get_property ("property-path"), + ev->get_property ("value")); } void Engraver_group::revert (SCM sev) { Stream_event *ev = unsmob (sev); + SCM sym = ev->get_property ("symbol"); + Grob_property_info gpi (context (), sym); - Grob_property_info (context (), ev->get_property ("symbol")) - .pop (ev->get_property ("property-path")); + if (to_boolean (ev->get_property ("once"))) + { + SCM token = gpi.temporary_revert (ev->get_property ("property-path")); + if (scm_is_pair (token)) + if (Global_context *g = context ()->get_global_context ()) + { + g->add_finalization (scm_list_4 (ly_context_matched_pop_property_proc, + context ()->self_scm (), + sym, + token)); + } + } + else + gpi.pop (ev->get_property ("property-path")); } void diff --git a/lily/include/context.hh b/lily/include/context.hh index 5461520350..b9aa6292b6 100644 --- a/lily/include/context.hh +++ b/lily/include/context.hh @@ -199,5 +199,8 @@ SCM assq_tail (SCM key, SCM alist, SCM alist_end); SCM assoc_tail (SCM key, SCM alist, SCM alist_end); SCM evict_from_alist (SCM, SCM, SCM); SCM nalist_to_alist (SCM nalist, int nested); +extern SCM ly_context_set_property_x_proc; +extern SCM ly_context_unset_property_proc; +extern SCM ly_context_matched_pop_property_proc; #endif /* CONTEXT_HH */ diff --git a/lily/include/property-iterator.hh b/lily/include/property-iterator.hh index 3f9577f6f7..984d41ef57 100644 --- a/lily/include/property-iterator.hh +++ b/lily/include/property-iterator.hh @@ -29,11 +29,9 @@ class Property_iterator : public Simple_music_iterator { public: DECLARE_SCHEME_CALLBACK (constructor, ()); - DECLARE_SCHEME_CALLBACK (once_finalization, (SCM, SCM, SCM)); DECLARE_CLASSNAME (Property_iterator); protected: - virtual void do_quit (); virtual void process (Moment); }; @@ -53,11 +51,9 @@ class Push_property_iterator : public Simple_music_iterator { public: DECLARE_SCHEME_CALLBACK (constructor, ()); - DECLARE_SCHEME_CALLBACK (once_finalization, (SCM, SCM)); DECLARE_CLASSNAME (Push_property_iterator); protected: virtual void process (Moment); - virtual void do_quit (); }; class Pop_property_iterator : public Simple_music_iterator diff --git a/lily/property-iterator.cc b/lily/property-iterator.cc index bf95ee21eb..4725406323 100644 --- a/lily/property-iterator.cc +++ b/lily/property-iterator.cc @@ -35,25 +35,11 @@ Property_iterator::process (Moment mom) { Context *o = get_outlet (); Music *m = get_music (); - bool once = to_boolean (m->get_property ("once")); - SCM symbol = m->get_property ("symbol"); - SCM previous_value = SCM_UNDEFINED; - if (once) - o->here_defined (symbol, &previous_value); send_stream_event (o, "SetProperty", m->origin (), - ly_symbol2scm ("symbol"), symbol, - ly_symbol2scm ("value"), m->get_property ("value")); - - /* For \once \set install a finalization hook to reset the property to the - * previous value after the timestep */ - if (once) - { - Global_context *tg = get_outlet ()->get_global_context (); - tg->add_finalization (scm_list_4 (once_finalization_proc, - o->self_scm (), m->self_scm (), - previous_value)); - } + ly_symbol2scm ("symbol"), m->get_property ("symbol"), + ly_symbol2scm ("value"), m->get_property ("value"), + ly_symbol2scm ("once"), m->get_property ("once")); Simple_music_iterator::process (mom); } @@ -63,47 +49,12 @@ Property_unset_iterator::process (Moment mom) { Context *o = get_outlet (); Music *m = get_music (); - bool once = to_boolean (m->get_property ("once")); - SCM symbol = m->get_property ("symbol"); - SCM previous_value = SCM_UNDEFINED; - if (once) - o->here_defined (symbol, &previous_value); send_stream_event (o, "UnsetProperty", m->origin (), - ly_symbol2scm ("symbol"), symbol); - - /* For \once \unset install a finalization hook to reset the property to the - * previous value after the timestep */ - if (once && !SCM_UNBNDP (previous_value)) - { - Global_context *tg = get_outlet ()->get_global_context (); - tg->add_finalization (scm_list_4 (Property_iterator::once_finalization_proc, - o->self_scm (), m->self_scm (), - previous_value)); - } - - Simple_music_iterator::process (mom); -} - -MAKE_SCHEME_CALLBACK (Property_iterator, once_finalization, 3); -SCM -Property_iterator::once_finalization (SCM ctx, SCM music, SCM previous_value) -{ - Music *m = unsmob (music); - Context *c = unsmob (ctx); - - // Do not use UnsetProperty, which sets the default, but rather - // cache the value before the \once \set command and restore it now - send_stream_event (c, "SetProperty", m->origin (), ly_symbol2scm ("symbol"), m->get_property ("symbol"), - ly_symbol2scm ("value"), previous_value); - - return SCM_UNSPECIFIED; -} + ly_symbol2scm ("once"), m->get_property ("once")); -void -Property_iterator::do_quit () -{ + Simple_music_iterator::process (mom); } bool @@ -140,9 +91,10 @@ Push_property_iterator::process (Moment m) { SCM grob_property_path = get_property_path (get_music ()); SCM val = get_music ()->get_property ("grob-value"); + SCM once = get_music ()->get_property ("once"); if (to_boolean (get_music ()->get_property ("pop-first")) - && !to_boolean (get_music ()->get_property ("once"))) + && !to_boolean (once)) send_stream_event (get_outlet (), "Revert", get_music ()->origin (), ly_symbol2scm ("symbol"), sym, ly_symbol2scm ("property-path"), grob_property_path); @@ -150,58 +102,28 @@ Push_property_iterator::process (Moment m) send_stream_event (get_outlet (), "Override", get_music ()->origin (), ly_symbol2scm ("symbol"), sym, ly_symbol2scm ("property-path"), grob_property_path, + ly_symbol2scm ("once"), once, ly_symbol2scm ("value"), val); } Simple_music_iterator::process (m); } -MAKE_SCHEME_CALLBACK (Push_property_iterator, once_finalization, 2); -SCM -Push_property_iterator::once_finalization (SCM ctx, SCM music) -{ - Music *mus = unsmob (music); - Context *c = unsmob (ctx); - - SCM sym = mus->get_property ("symbol"); - if (check_grob (mus, sym)) - { - SCM grob_property_path = get_property_path (mus); - - send_stream_event (c, "Revert", mus->origin (), - ly_symbol2scm ("symbol"), sym, - ly_symbol2scm ("property-path"), grob_property_path); - } - return SCM_UNSPECIFIED; -} - void -Push_property_iterator::do_quit () +Pop_property_iterator::process (Moment mom) { - if (to_boolean (get_music ()->get_property ("once"))) - { - SCM trans = get_outlet ()->self_scm (); - SCM music = get_music ()->self_scm (); - - Global_context *tg = get_outlet ()->get_global_context (); - tg->add_finalization (scm_list_3 (once_finalization_proc, - trans, music)); - } -} - -void -Pop_property_iterator::process (Moment m) -{ - SCM sym = get_music ()->get_property ("symbol"); + Music *m = get_music (); + SCM sym = m->get_property ("symbol"); - if (check_grob (get_music (), sym)) + if (check_grob (m, sym)) { - SCM grob_property_path = get_property_path (get_music ()); + SCM grob_property_path = get_property_path (m); - send_stream_event (get_outlet (), "Revert", get_music ()->origin (), + send_stream_event (get_outlet (), "Revert", m->origin (), ly_symbol2scm ("symbol"), sym, + ly_symbol2scm ("once"), m->get_property ("once"), ly_symbol2scm ("property-path"), grob_property_path); } - Simple_music_iterator::process (m); + Simple_music_iterator::process (mom); } IMPLEMENT_CTOR_CALLBACK (Pop_property_iterator);