2 context-property.cc -- implement manipulation of immutable Grob
5 source file of the GNU LilyPond music typesetter
7 (c) 2004--2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
11 #include "engraver.hh"
18 Grob descriptions (ie. alists with layout properties) are
19 represented as a (ALIST . BASED-ON) pair, where BASED-ON is the
20 alist defined in a parent context. BASED-ON should always be a tail
25 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
26 entry from a translator property list by name of PROP
30 execute_pushpop_property (Context *trg,
31 SCM prop, SCM eltprop, SCM val)
33 if (scm_is_symbol (prop) && scm_is_symbol (eltprop))
35 if (val != SCM_UNDEFINED)
38 Context *where = trg->where_defined (prop);
48 SCM base = updated_grob_properties (trg, prop);
49 prev = scm_cons (base, base);
50 trg->internal_set_property (prop, prev);
53 prev = trg->internal_get_property (prop);
55 if (!scm_is_pair (prev))
57 programming_error ("Grob definition should be cons");
61 SCM prev_alist = scm_car (prev);
63 if (scm_is_pair (prev_alist) || prev_alist == SCM_EOL)
65 bool ok = type_check_assignment (eltprop, val, ly_symbol2scm ("backend-type?"));
71 scm_set_car_x (prev, scm_acons (eltprop, val, prev_alist));
78 else if (trg->where_defined (prop) == trg)
80 SCM prev = trg->internal_get_property (prop);
81 SCM prev_alist = scm_car (prev);
82 SCM daddy = scm_cdr (prev);
84 SCM new_alist = SCM_EOL;
85 SCM *tail = &new_alist;
87 while (prev_alist != daddy)
89 if (ly_is_equal (scm_caar (prev_alist), eltprop))
91 prev_alist = scm_cdr (prev_alist);
95 *tail = scm_cons (scm_car (prev_alist), SCM_EOL);
96 tail = SCM_CDRLOC (*tail);
97 prev_alist = scm_cdr (prev_alist);
100 if (new_alist == SCM_EOL && prev_alist == daddy)
101 trg->unset_property (prop);
105 trg->internal_set_property (prop, scm_cons (new_alist, daddy));
111 warning (_ ("need symbol arguments for \\override and \\revert"));
112 if (do_internal_type_checking_global)
118 PRE_INIT_OPS is in the order specified, and hence must be reversed.
121 apply_property_operations (Context *tg, SCM pre_init_ops)
123 SCM correct_order = scm_reverse (pre_init_ops);
124 for (SCM s = correct_order; scm_is_pair (s); s = scm_cdr (s))
126 SCM entry = scm_car (s);
127 SCM type = scm_car (entry);
128 entry = scm_cdr (entry);
130 if (type == ly_symbol2scm ("push") || type == ly_symbol2scm ("poppush"))
132 SCM val = scm_cddr (entry);
133 val = scm_is_pair (val) ? scm_car (val) : SCM_UNDEFINED;
135 execute_pushpop_property (tg, scm_car (entry), scm_cadr (entry), val);
137 else if (type == ly_symbol2scm ("assign"))
139 tg->internal_set_property (scm_car (entry), scm_cadr (entry));
145 Return the object alist for SYM, checking if its base in enclosing
146 contexts has changed. The alist is updated if necessary.
149 updated_grob_properties (Context *tg, SCM sym)
151 assert (scm_is_symbol (sym));
153 tg = tg->where_defined (sym);
158 = (tg->get_parent_context ())
159 ? updated_grob_properties (tg->get_parent_context (), sym)
162 SCM props = tg->internal_get_property (sym);
164 if (!scm_is_pair (props))
166 programming_error ("grob props not a pair?");
170 SCM based_on = scm_cdr (props);
171 if (based_on == daddy_props)
173 return scm_car (props);
177 SCM copy = daddy_props;
179 SCM p = scm_car (props);
180 while (p != based_on)
182 *tail = scm_cons (scm_car (p), daddy_props);
183 tail = SCM_CDRLOC (*tail);
187 scm_set_car_x (props, copy);
188 scm_set_cdr_x (props, daddy_props);
195 make_item_from_properties (Engraver *tr, SCM x, SCM cause, const char *name)
197 Context *context = tr->context ();
199 SCM props = updated_grob_properties (context, x);
201 Object_key const *key = context->get_grob_key (name);
202 Item *it = new Item (props, key);
204 dynamic_cast<Engraver *> (tr)->announce_grob (it, cause);
210 make_spanner_from_properties (Engraver *tr, SCM x, SCM cause, const char *name)
212 Context *context = tr->context ();
214 SCM props = updated_grob_properties (context, x);
215 Spanner *it = new Spanner (props, context->get_grob_key (name));
217 dynamic_cast<Engraver *> (tr)->announce_grob (it, cause);