]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/context-property.cc
Fix 453.
[lilypond.git] / lily / context-property.cc
index 81bb7c588175d56a0ddb5122320e026d53815479..4645901b371afbae7d6e440e417dcef333bd4402 100644 (file)
@@ -4,7 +4,7 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 2004--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  (c) 2004--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
 */
 
 #include "context.hh"
 #include "warn.hh"
 
 /*
-  copy ALIST leaving out SYMBOL. Copying stops at ALIST_END
+  like execute_general_pushpop_property(), but typecheck
+  grob_property_path and context_property.
 */
-SCM
-evict_from_alist (SCM symbol,
-                 SCM alist,
-                 SCM alist_end)
-{
-  SCM new_alist = SCM_EOL;
-  SCM *tail = &new_alist;
-
-  while (alist != alist_end)
-    {
-      if (ly_is_equal (scm_caar (alist), symbol))
-       {
-         alist = scm_cdr (alist);
-         break;
-       }
-
-      *tail = scm_cons (scm_car (alist), SCM_EOL);
-      tail = SCM_CDRLOC (*tail);
-      alist = scm_cdr (alist);
-    }
-
-  *tail = alist;
-  return new_alist;
-}
-
 void
 general_pushpop_property (Context *context,
                          SCM context_property,
                          SCM grob_property_path,
-                         SCM new_value                   
-                         )
+                         SCM new_value)
 {
   if (!scm_is_symbol (context_property)
       || !scm_is_symbol (scm_car (grob_property_path)))
@@ -59,13 +34,12 @@ general_pushpop_property (Context *context,
        assert (false);
     }
 
-  execute_general_pushpop_property (context, context_property,
+  sloppy_general_pushpop_property (context, context_property,
                                    grob_property_path, new_value);
 }
 
 
 /*
-  
   Grob descriptions (ie. alists with layout properties) are
   represented as a (ALIST . BASED-ON) pair, where BASED-ON is the
   alist defined in a parent context. BASED-ON should always be a tail
@@ -76,8 +50,6 @@ general_pushpop_property (Context *context,
   indicates nested alists, eg. '(beamed-stem-lengths details)
   
 */
-
-
 void
 execute_override_property (Context *context,
                           SCM context_property,
@@ -108,8 +80,9 @@ execute_override_property (Context *context,
       return;
     }
 
-  SCM symbol = scm_car (grob_property_path);
   SCM target_alist = scm_car (current_context_val);
+
+  SCM symbol = scm_car (grob_property_path);
   if (scm_is_pair (scm_cdr (grob_property_path)))
     {
       new_value = nested_property_alist (ly_assoc_get (symbol, target_alist, 
@@ -118,10 +91,10 @@ execute_override_property (Context *context,
                                         new_value);
     }
 
-  if (scm_is_pair (target_alist)
-      && scm_caar (target_alist) == symbol)
-    target_alist = scm_cdr (target_alist);
-
+  /* it's tempting to replace the head of the list if it's the same
+   property. However, we have to keep this info around, in case we have to
+   \revert back to it.
+  */
   target_alist = scm_acons (symbol, new_value, target_alist);
 
   bool ok = true;
@@ -141,30 +114,37 @@ execute_override_property (Context *context,
     }
 }
 
-         
+/*
+  do a pop (indicated by new_value==SCM_UNDEFINED) or push
+ */
 void
-execute_general_pushpop_property (Context *context,
-                                 SCM context_property,
-                                 SCM grob_property_path,
-                                 SCM new_value
-                                 )
+sloppy_general_pushpop_property (Context *context,
+                                SCM context_property,
+                                SCM grob_property_path,
+                                SCM new_value)
 {
-  if (new_value != SCM_UNDEFINED)
-    {
-      execute_override_property (context, context_property,
-                                grob_property_path,
-                                new_value);
-
-      return;
-    }
+  if (new_value == SCM_UNDEFINED)
+    execute_revert_property (context, context_property,
+                            grob_property_path);
+  else
+    execute_override_property (context, context_property,
+                              grob_property_path,
+                              new_value);
+}
 
-  /*
-    revert.
-   */
+/*
+  Revert the property given by property_path.
+*/
+void
+execute_revert_property (Context *context,
+                        SCM context_property,
+                        SCM grob_property_path)
+{
   SCM current_context_val = SCM_EOL;
-  if (context->where_defined (context_property, &current_context_val) == context)
+  if (context->where_defined (context_property, &current_context_val)
+      == context)
     {
-      SCM current_value = scm_car (current_context_val);
+      SCM current_alist = scm_car (current_context_val);
       SCM daddy = scm_cdr (current_context_val);
 
       if (!scm_is_pair (grob_property_path)
@@ -175,21 +155,42 @@ execute_general_pushpop_property (Context *context,
        }
       
       SCM symbol = scm_car (grob_property_path);
-      SCM new_alist = evict_from_alist (symbol, current_value, daddy);
-
-      if (new_alist == daddy)
-       context->unset_property (context_property);
+      if (scm_is_pair (scm_cdr (grob_property_path)))
+       {
+         SCM current_sub_alist = ly_assoc_get (symbol, current_alist, SCM_EOL);
+         SCM new_val
+           = nested_property_revert_alist (current_sub_alist,
+                                           scm_cdr (grob_property_path));
+           
+         if (scm_is_pair (current_alist)
+             && scm_caar (current_alist) == symbol
+             && current_alist != daddy)
+           current_alist = scm_cdr (current_alist);
+
+         current_alist = scm_acons (symbol, new_val, current_alist);
+         scm_set_car_x (current_context_val, current_alist);
+       }
       else
-       context->set_property (context_property, scm_cons (new_alist, daddy));
+       {
+         SCM new_alist = evict_from_alist (symbol, current_alist, daddy);
+         
+         if (new_alist == daddy)
+           context->unset_property (context_property);
+         else
+           context->set_property (context_property,
+                                  scm_cons (new_alist, daddy));
+       }
     }
 }
-
+/*
+  Convenience: a push/pop grob property using a single grob_property
+  as argument.
+*/
 void
 execute_pushpop_property (Context *context,
                          SCM context_property,
                          SCM grob_property,
-                         SCM new_value
-                         )
+                         SCM new_value)
 {
   general_pushpop_property (context, context_property,
                            scm_list_1 (grob_property),
@@ -214,14 +215,14 @@ apply_property_operations (Context *tg, SCM pre_init_ops)
          SCM context_prop = scm_car (entry);
          SCM val = scm_cadr (entry);
          SCM grob_prop_path = scm_cddr (entry);
-         execute_general_pushpop_property (tg, context_prop, grob_prop_path, val);
+         sloppy_general_pushpop_property (tg, context_prop, grob_prop_path, val);
        }
       else if (type == ly_symbol2scm ("pop"))
        {
          SCM context_prop = scm_car (entry);
          SCM val = SCM_UNDEFINED;
          SCM grob_prop_path = scm_cdr (entry);
-         execute_general_pushpop_property (tg, context_prop, grob_prop_path, val);
+         sloppy_general_pushpop_property (tg, context_prop, grob_prop_path, val);
        }
       else if (type == ly_symbol2scm ("assign"))
        tg->set_property (scm_car (entry), scm_cadr (entry));