X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fcontext-property.cc;h=6e22b2f808211b28aaa7acedad6afba52f9829f6;hb=97a0169312a260933246ab224e4f8b0969871dd5;hp=45b5d496c12b522495c902010de87333afdff186;hpb=f5e923a6ce8cebb7ef893c03ce56aa5e598002c9;p=lilypond.git diff --git a/lily/context-property.cc b/lily/context-property.cc index 45b5d496c1..6e22b2f808 100644 --- a/lily/context-property.cc +++ b/lily/context-property.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2004--2014 Han-Wen Nienhuys + Copyright (C) 2004--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 @@ -24,7 +24,6 @@ #include "international.hh" #include "item.hh" #include "main.hh" -#include "simple-closure.hh" #include "smobs.hh" #include "spanner.hh" #include "unpure-pure-container.hh" @@ -40,10 +39,11 @@ general_pushpop_property (Context *context, SCM grob_property_path, SCM new_value) { + // Numbers may appear, but not in first place if (!scm_is_symbol (context_property) || !scm_is_symbol (scm_car (grob_property_path))) { - warning (_ ("need symbol arguments for \\override and \\revert")); + warning (_ ("need symbol argument for \\override and \\revert")); if (do_internal_type_checking_global) assert (false); } @@ -55,19 +55,18 @@ general_pushpop_property (Context *context, bool typecheck_grob (SCM symbol, SCM value) { - if (Unpure_pure_container *upc = Unpure_pure_container::unsmob (value)) + if (Unpure_pure_container *upc = unsmob (value)) return typecheck_grob (symbol, upc->unpure_part ()) && typecheck_grob (symbol, upc->pure_part ()); return ly_is_procedure (value) - || Simple_closure::is_smob (value) || type_check_assignment (symbol, value, ly_symbol2scm ("backend-type?")); } class Grob_properties : public Simple_smob { public: - SCM mark_smob (); - static const char type_p_name_[]; + SCM mark_smob () const; + static const char * const type_p_name_; private: friend class Grob_property_info; friend SCM ly_make_grob_properties (SCM); @@ -82,7 +81,11 @@ private: // cooked_from_ is the value of alist_ from which the expansion has // been done SCM cooked_from_; - // nested_ is a count of nested overrides in alist_ + // nested_ is a count of nested overrides in alist_ Or rather: of + // entries that must not appear in the cooked list and are + // identified by having a "key" that is not a symbol. Temporary + // overrides and reverts also meet that description and have a + // nominal key of #t/#f and a value of the original cons cell. int nested_; Grob_properties (SCM alist, SCM based_on) : @@ -94,10 +97,10 @@ private: cooked_ (alist), cooked_from_ (alist), nested_ (0) { } }; -const char Grob_properties::type_p_name_[] = "ly:grob-properties?"; +const char * const Grob_properties::type_p_name_ = "ly:grob-properties?"; SCM -Grob_properties::mark_smob () +Grob_properties::mark_smob () const { scm_gc_mark (alist_); scm_gc_mark (based_on_); @@ -124,8 +127,8 @@ Grob_property_info::find () SCM res = SCM_UNDEFINED; if (Context *c = context_->where_defined (symbol_, &res)) if (c != context_) - return Grob_property_info (c, symbol_, Grob_properties::unsmob (res)); - props_ = Grob_properties::unsmob (res); + return Grob_property_info (c, symbol_, unsmob (res)); + props_ = unsmob (res); return *this; } @@ -136,7 +139,7 @@ Grob_property_info::check () return true; SCM res = SCM_UNDEFINED; if (context_->here_defined (symbol_, &res)) - props_ = Grob_properties::unsmob (res); + props_ = unsmob (res); return props_; } @@ -165,7 +168,7 @@ Grob_property_info::create () || !g->here_defined (symbol_, ¤t_context_val)) return false; - Grob_properties *def = Grob_properties::unsmob (current_context_val); + Grob_properties *def = unsmob (current_context_val); if (!def) { @@ -180,7 +183,7 @@ Grob_property_info::create () // any, they will be factored in when `updated' is being called. SCM props = Grob_properties (def->alist_, def->alist_).smobbed_copy (); context_->set_property (symbol_, props); - props_ = Grob_properties::unsmob (props); + props_ = unsmob (props); return props_; } @@ -190,18 +193,21 @@ Grob_property_info::create () alist defined in a parent context. BASED-ON should always be a tail of ALIST. - Push or pop (depending on value of VAL) a single entry from a + Push a single entry from a translator property list by name of PROP. GROB_PROPERTY_PATH indicates nested alists, eg. '(beamed-stem-lengths details) + + Return value can be passed to matched_pop and will only cancel the + same override then. */ -void +SCM Grob_property_info::push (SCM grob_property_path, SCM new_value) { /* Don't mess with MIDI. */ if (!create ()) - return; + return SCM_EOL; SCM symbol = scm_car (grob_property_path); SCM rest = scm_cdr (grob_property_path); @@ -209,10 +215,12 @@ Grob_property_info::push (SCM grob_property_path, SCM new_value) { // poor man's typechecking if (typecheck_grob (symbol, nested_create_alist (rest, new_value))) { - props_->alist_ = scm_acons (grob_property_path, new_value, props_->alist_); + SCM cell = scm_cons (grob_property_path, new_value); + props_->alist_ = scm_cons (cell, props_->alist_); props_->nested_++; + return cell; } - return; + return SCM_EOL; } /* it's tempting to replace the head of the list if it's the same @@ -221,7 +229,98 @@ Grob_property_info::push (SCM grob_property_path, SCM new_value) */ if (typecheck_grob (symbol, new_value)) - props_->alist_ = scm_acons (symbol, new_value, props_->alist_); + { + SCM cell = scm_cons (symbol, new_value); + props_->alist_ = scm_cons (cell, props_->alist_); + return cell; + } + return SCM_EOL; +} + +// Used for \once \override, returns a token for matched_pop +SCM +Grob_property_info::temporary_override (SCM grob_property_path, SCM new_value) +{ + SCM cell = push (grob_property_path, new_value); + if (!scm_is_pair (cell)) + return cell; + if (scm_is_symbol (scm_car (cell))) + props_->nested_++; + cell = scm_cons (SCM_BOOL_T, cell); + props_->alist_ = scm_cons (cell, scm_cdr (props_->alist_)); + return cell; +} + +// Used for \once \revert, returns a token for matched_pop +SCM +Grob_property_info::temporary_revert (SCM grob_property_path) +{ + if (!check ()) + return SCM_EOL; + + SCM current_alist = props_->alist_; + SCM daddy = props_->based_on_; + SCM tail = SCM_EOL; + + if (!scm_is_pair (grob_property_path) + || !scm_is_symbol (scm_car (grob_property_path))) + { + programming_error ("Grob property path should be list of symbols."); + return SCM_EOL; + } + + if (scm_is_pair (scm_cdr (grob_property_path))) + { + tail = assoc_tail (grob_property_path, current_alist, daddy); + if (scm_is_false (tail)) + return SCM_EOL; + } + else + { + tail = assq_tail (scm_car (grob_property_path), current_alist, daddy); + if (scm_is_false (tail)) + return SCM_EOL; + ++props_->nested_; + } + + SCM cell = scm_cons (SCM_BOOL_F, scm_car (tail)); + props_->alist_ = partial_list_copy (current_alist, tail, + scm_cons (cell, scm_cdr (tail))); + return cell; +} + + +void +Grob_property_info::matched_pop (SCM cell) +{ + if (!scm_is_pair (cell)) + return; + if (!check ()) + return; + SCM current_alist = props_->alist_; + SCM daddy = props_->based_on_; + for (SCM p = current_alist; !scm_is_eq (p, daddy); p = scm_cdr (p)) + { + if (scm_is_eq (scm_car (p), cell)) + { + SCM key = scm_car (cell); + if (scm_is_false (key)) + { + // temporary revert, reactivate + cell = scm_cdr (cell); + if (scm_is_symbol (scm_car (cell))) + props_->nested_--; + props_->alist_ = partial_list_copy (current_alist, p, + scm_cons (cell, scm_cdr (p))); + return; + } + if (!scm_is_symbol (key)) + props_->nested_--; + props_->alist_ = partial_list_copy (current_alist, p, scm_cdr (p)); + return; + } + } + return; } /* @@ -289,24 +388,24 @@ apply_property_operations (Context *tg, SCM pre_init_ops) SCM type = scm_car (entry); entry = scm_cdr (entry); - if (type == ly_symbol2scm ("push")) + if (scm_is_eq (type, ly_symbol2scm ("push"))) { SCM context_prop = scm_car (entry); SCM val = scm_cadr (entry); SCM grob_prop_path = scm_cddr (entry); Grob_property_info (tg, context_prop).push (grob_prop_path, val); } - else if (type == ly_symbol2scm ("pop")) + else if (scm_is_eq (type, ly_symbol2scm ("pop"))) { SCM context_prop = scm_car (entry); SCM grob_prop_path = scm_cdr (entry); Grob_property_info (tg, context_prop).pop (grob_prop_path); } - else if (type == ly_symbol2scm ("assign")) + else if (scm_is_eq (type, ly_symbol2scm ("assign"))) tg->set_property (scm_car (entry), scm_cadr (entry)); - else if (type == ly_symbol2scm ("apply")) - scm_apply_1 (scm_car (entry), tg->self_scm (), scm_cdr (entry)); - else if (type == ly_symbol2scm ("unset")) + else if (scm_is_eq (type, ly_symbol2scm ("apply"))) + scm_apply_1 (scm_car (entry), tg->self_scm (), scm_cdr (entry)); + else if (scm_is_eq (type, ly_symbol2scm ("unset"))) tg->unset_property (scm_car (entry)); } }