+/**
+ Remove a context from the hierarchy.
+*/
+Context *
+Context::remove_context (Context *trans)
+{
+ assert (trans);
+
+ context_list_ = scm_delq_x (trans->self_scm (), context_list_);
+ trans->daddy_context_ = 0;
+ return trans;
+}
+
+/*
+ ID == "" means accept any ID.
+*/
+Context *
+find_context_below (Context *where,
+ SCM type, String id)
+{
+ if (where->is_alias (type))
+ {
+ if (id == "" || where->id_string () == id)
+ return where;
+ }
+
+ Context *found = 0;
+ for (SCM s = where->children_contexts ();
+ !found && scm_is_pair (s); s = scm_cdr (s))
+ {
+ Context *tr = unsmob_context (scm_car (s));
+
+ found = find_context_below (tr, type, id);
+ }
+
+ return found;
+}
+
+SCM
+Context::properties_as_alist () const
+{
+ return properties_dict ()->to_alist ();
+}
+
+SCM
+Context::context_name_symbol () const
+{
+ Context_def *td = unsmob_context_def (definition_);
+ return td->get_context_name ();
+}
+
+String
+Context::context_name () const
+{
+ return ly_symbol2string (context_name_symbol ());
+}
+
+Score_context *
+Context::get_score_context () const
+{
+ if (Score_context *sc = dynamic_cast<Score_context *> ((Context *) this))
+ return sc;
+ else if (daddy_context_)
+ return daddy_context_->get_score_context ();
+ else
+ return 0;
+}
+
+Output_def *
+Context::get_output_def () const
+{
+ return daddy_context_ ? daddy_context_->get_output_def () : 0;
+}
+
+Context::~Context ()
+{
+}
+
+Moment
+Context::now_mom () const
+{
+ return daddy_context_->now_mom ();
+}
+
+int
+Context::print_smob (SCM s, SCM port, scm_print_state *)
+{
+ Context *sc = (Context *) SCM_CELL_WORD_1 (s);
+
+ scm_puts ("#<", port);
+ scm_puts (classname (sc), port);
+ if (Context_def *d = unsmob_context_def (sc->definition_))
+ {
+ scm_puts (" ", port);
+ scm_display (d->get_context_name (), port);
+ }
+
+ if (Context *td = dynamic_cast<Context *> (sc))
+ {
+ scm_puts ("=", port);
+ scm_puts (td->id_string_.to_str0 (), port);
+ }
+
+ scm_puts (" ", port);
+
+ scm_display (sc->context_list_, port);
+ scm_puts (" >", port);
+
+ return 1;
+}
+
+SCM
+Context::mark_smob (SCM sm)
+{
+ Context *me = (Context *) SCM_CELL_WORD_1 (sm);
+ scm_gc_mark (me->key_->self_scm ());
+ scm_gc_mark (me->context_list_);
+ scm_gc_mark (me->aliases_);
+ scm_gc_mark (me->definition_);
+ scm_gc_mark (me->properties_scm_);
+ scm_gc_mark (me->accepts_list_);
+ scm_gc_mark (me->implementation_);
+
+ return me->properties_scm_;
+}
+
+IMPLEMENT_SMOBS (Context);
+IMPLEMENT_DEFAULT_EQUAL_P (Context);
+IMPLEMENT_TYPE_P (Context, "ly:context?");
+
+bool
+Context::try_music (Music *m)
+{
+ Translator *t = implementation ();
+ if (!t)
+ return false;
+
+ bool b = t->try_music (m);
+ if (!b && daddy_context_)
+ b = daddy_context_->try_music (m);
+
+ return b;
+}
+
+Global_context *
+Context::get_global_context () const
+{
+ if (dynamic_cast<Global_context *> ((Context *) this))
+ return dynamic_cast<Global_context *> ((Context *) this);
+
+ if (daddy_context_)
+ return daddy_context_->get_global_context ();
+
+ programming_error ("no Global context");
+ return 0;
+}
+
+Context *
+Context::get_parent_context () const
+{
+ return daddy_context_;
+}
+
+Translator_group *
+Context::implementation () const
+{
+ return dynamic_cast<Translator_group *> (unsmob_translator (implementation_));
+}
+
+void
+Context::clear_key_disambiguations ()
+{
+ grob_counts_.clear ();
+ context_counts_.clear ();
+ for (SCM s = context_list_; scm_is_pair (s); s = scm_cdr (s))
+ {
+ unsmob_context (scm_car (s))->clear_key_disambiguations ();
+ }
+}