X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fengraver-group.cc;h=c431d10ae13cd35e83e6130e1e8bf09a4ac6a405;hb=a6a51abfd0195a3cf7d6ea095cf69808852f21ce;hp=97e9277fcccdc96e033d192860d3961b34514a96;hpb=3dfd0a47e01374e0d8d1e6b127fa3f7a15a53edc;p=lilypond.git diff --git a/lily/engraver-group.cc b/lily/engraver-group.cc index 97e9277fcc..c431d10ae1 100644 --- a/lily/engraver-group.cc +++ b/lily/engraver-group.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1997--2014 Han-Wen Nienhuys + Copyright (C) 1997--2015 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,60 +20,85 @@ #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" #include "translator-dispatch-list.hh" #include "warn.hh" -IMPLEMENT_LISTENER (Engraver_group, override); void Engraver_group::override (SCM sev) { - Stream_event *ev = Stream_event::unsmob (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")); } -IMPLEMENT_LISTENER (Engraver_group, revert); void Engraver_group::revert (SCM sev) { - Stream_event *ev = Stream_event::unsmob (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 Engraver_group::connect_to_context (Context *c) { Translator_group::connect_to_context (c); - c->event_source ()->add_listener (GET_LISTENER (override), ly_symbol2scm ("Override")); - c->event_source ()->add_listener (GET_LISTENER (revert), ly_symbol2scm ("Revert")); + c->event_source ()->add_listener (GET_LISTENER (Engraver_group, override), ly_symbol2scm ("Override")); + c->event_source ()->add_listener (GET_LISTENER (Engraver_group, revert), ly_symbol2scm ("Revert")); } void Engraver_group::disconnect_from_context () { - context ()->event_source ()->remove_listener (GET_LISTENER (override), ly_symbol2scm ("Override")); - context ()->event_source ()->remove_listener (GET_LISTENER (revert), ly_symbol2scm ("Revert")); + context ()->event_source ()->remove_listener (GET_LISTENER (Engraver_group, override), ly_symbol2scm ("Override")); + context ()->event_source ()->remove_listener (GET_LISTENER (Engraver_group, revert), ly_symbol2scm ("Revert")); Translator_group::disconnect_from_context (); } void -Engraver_group::announce_grob (Grob_info info) +Engraver_group::announce_grob (Grob_info info, Direction dir, + Context *reroute_context) { - announce_infos_.push_back (info); + announce_infos_.push_back (Announce_grob_info (info, dir)); - Context *dad_con = context_->get_parent_context (); - if (info.rerouting_daddy_context_) - { - dad_con = info.rerouting_daddy_context_; - info.rerouting_daddy_context_ = 0; - } + Context *dad_con = reroute_context ? reroute_context + : context_->get_parent_context (); Engraver_group *dad_eng = dad_con @@ -81,7 +106,7 @@ Engraver_group::announce_grob (Grob_info info) : 0; if (dad_eng) - dad_eng->announce_grob (info); + dad_eng->announce_grob (info, dir); } void @@ -94,7 +119,7 @@ Engraver_group::acknowledge_grobs () for (vsize j = 0; j < announce_infos_.size (); j++) { - Grob_info info = announce_infos_[j]; + Announce_grob_info info = announce_infos_[j]; SCM meta = info.grob ()->get_property ("meta"); SCM nm = scm_assoc (name_sym, meta); @@ -103,25 +128,24 @@ Engraver_group::acknowledge_grobs () else continue; - SCM acklist = scm_hashq_ref (acknowledge_hash_table_drul_[info.start_end ()], - nm, SCM_BOOL_F); + SCM ackhandle = scm_hashq_create_handle_x (acknowledge_hash_table_drul_[info.start_end ()], + nm, SCM_BOOL_F); - Engraver_dispatch_list *dispatch - = Engraver_dispatch_list::unsmob (acklist); + SCM acklist = scm_cdr (ackhandle); - if (acklist == SCM_BOOL_F) + if (scm_is_false (acklist)) { SCM ifaces = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta)); acklist = Engraver_dispatch_list::create (get_simple_trans_list (), ifaces, info.start_end ()); - dispatch - = Engraver_dispatch_list::unsmob (acklist); - - scm_hashq_set_x (acknowledge_hash_table_drul_[info.start_end ()], nm, acklist); + scm_set_cdr_x (ackhandle, acklist); } + Engraver_dispatch_list *dispatch + = unsmob (acklist); + if (dispatch) dispatch->apply (info); } @@ -131,21 +155,22 @@ Engraver_group::acknowledge_grobs () Ugh. This is slightly expensive. We could/should cache the value of the group count? */ -int -Engraver_group::pending_grob_count () const +bool +Engraver_group::pending_grobs () const { - int count = announce_infos_.size (); + if (!announce_infos_.empty ()) + return true; for (SCM s = context_->children_contexts (); scm_is_pair (s); s = scm_cdr (s)) { - Context *c = Context::unsmob (scm_car (s)); + Context *c = unsmob (scm_car (s)); Engraver_group *group = dynamic_cast (c->implementation ()); - if (group) - count += group->pending_grob_count (); + if (group && group->pending_grobs ()) + return true; } - return count; + return false; } void @@ -159,7 +184,7 @@ Engraver_group::do_announces () for (SCM s = context ()->children_contexts (); scm_is_pair (s); s = scm_cdr (s)) { - Context *c = Context::unsmob (scm_car (s)); + Context *c = unsmob (scm_car (s)); Engraver_group *group = dynamic_cast (c->implementation ()); if (group) @@ -176,15 +201,16 @@ Engraver_group::do_announces () announce_infos_.clear (); } } - while (pending_grob_count () > 0); + while (pending_grobs ()); } -Engraver_group::Engraver_group () +Preinit_Engraver_group::Preinit_Engraver_group () { - acknowledge_hash_table_drul_[LEFT] - = acknowledge_hash_table_drul_[RIGHT] - = SCM_EOL; + acknowledge_hash_table_drul_.set (SCM_EOL, SCM_EOL); +} +Engraver_group::Engraver_group () +{ acknowledge_hash_table_drul_[LEFT] = scm_c_make_hash_table (61); acknowledge_hash_table_drul_[RIGHT] = scm_c_make_hash_table (61); }