+
+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;
+}
+
+/*
+ Revert the property given by property_path.
+*/
+void
+Grob_property_info::pop (SCM grob_property_path)
+{
+ if (!check ())
+ return;
+
+ SCM current_alist = props_->alist_;
+ SCM daddy = props_->based_on_;
+
+ 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;
+ }
+
+ if (scm_is_pair (scm_cdr (grob_property_path)))
+ {
+ SCM old_alist = current_alist;
+ current_alist = evict_from_alist (grob_property_path, current_alist, daddy);
+ if (scm_is_eq (old_alist, current_alist))
+ return;
+ props_->nested_--;
+ }
+ else
+ current_alist = evict_from_alist (scm_car (grob_property_path),
+ current_alist, daddy);
+
+ if (scm_is_eq (current_alist, daddy))
+ {
+ assert (props_->nested_ == 0);
+ props_ = 0;
+ context_->unset_property (symbol_);
+ return;
+ }
+ props_->alist_ = current_alist;
+}
+/*
+ Convenience: a push/pop grob property using a single grob_property
+ as argument.
+*/