2 translator-property.cc -- implement manipulation of
4 immutable Grob property lists.
6 source file of the GNU LilyPond music typesetter
8 (c) 2004 Han-Wen Nienhuys <hanwen@xs4all.nl>
12 #include "translator-group.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
26 Push or pop (depending on value of VAL) a single entry (ELTPROP . VAL)
27 entry from a translator property list by name of PROP
32 execute_pushpop_property (Translator_group * trg,
33 SCM prop, SCM eltprop, SCM val)
35 if (gh_symbol_p (prop) && gh_symbol_p (eltprop))
37 if (val != SCM_UNDEFINED)
40 Translator_group * where = trg->where_defined (prop);
49 SCM base = updated_grob_properties (trg, prop);
50 prev = gh_cons (base, base);
51 trg->internal_set_property (prop, prev);
54 prev = trg->internal_get_property (prop);
56 if (!gh_pair_p (prev))
58 programming_error ("Grob definition should be cons.");
62 SCM prev_alist = gh_car (prev);
64 if (gh_pair_p (prev_alist) || prev_alist == SCM_EOL)
66 bool ok = type_check_assignment (eltprop, val, ly_symbol2scm ("backend-type?"));
72 gh_set_car_x (prev, scm_acons (eltprop, val, prev_alist));
79 else if (trg->where_defined (prop) == trg)
81 SCM prev = trg->internal_get_property (prop);
82 SCM prev_alist = gh_car (prev);
83 SCM daddy = gh_cdr (prev);
85 SCM new_alist = SCM_EOL;
86 SCM *tail = &new_alist;
88 while (prev_alist != daddy)
90 if (!gh_equal_p (gh_caar (prev_alist), eltprop))
92 *tail = gh_cons (gh_car (prev_alist), daddy);
93 tail = SCM_CDRLOC (*tail);
95 prev_alist = gh_cdr (prev_alist);
98 if (new_alist == SCM_EOL)
99 trg->unset_property (prop);
101 trg->internal_set_property (prop, gh_cons (new_alist, daddy));
106 warning ("Need symbol arguments for \\override and \\revert");
107 if (internal_type_checking_global_b)
113 PRE_INIT_OPS is in the order specified, and hence must be reversed.
116 apply_property_operations (Translator_group*tg, SCM pre_init_ops)
118 SCM correct_order = scm_reverse (pre_init_ops);
119 for (SCM s = correct_order; gh_pair_p (s); s = ly_cdr (s))
121 SCM entry = ly_car (s);
122 SCM type = ly_car (entry);
123 entry = ly_cdr (entry);
125 if (type == ly_symbol2scm ("push") || type == ly_symbol2scm ("poppush"))
127 SCM val = ly_cddr (entry);
128 val = gh_pair_p (val) ? ly_car (val) : SCM_UNDEFINED;
130 execute_pushpop_property (tg, ly_car (entry), ly_cadr (entry), val);
132 else if (type == ly_symbol2scm ("assign"))
134 tg->internal_set_property (ly_car (entry), ly_cadr (entry));
140 Return the object alist for SYM, checking if its base in enclosing
141 contexts has changed. The alist is updated if necessary.
144 updated_grob_properties (Translator_group* tg, SCM sym)
146 assert (gh_symbol_p (sym));
148 tg = tg->where_defined (sym);
151 ? updated_grob_properties (tg->daddy_trans_, sym)
154 SCM props = tg->internal_get_property (sym);
156 if (!gh_pair_p (props))
158 programming_error ("grob props not a pair?");
162 SCM based_on = gh_cdr (props);
163 if (based_on == daddy_props)
165 return gh_car (props);
169 SCM copy = daddy_props;
171 SCM p = gh_car (props);
172 while (p != based_on)
174 *tail = gh_cons (gh_car (p), daddy_props);
175 tail = SCM_CDRLOC (*tail);
179 scm_set_car_x (props, copy);
180 scm_set_cdr_x (props, daddy_props);
187 make_item_from_properties (Translator_group* tg, SCM x)
189 SCM props = updated_grob_properties (tg, x);
190 return new Item (props);
194 make_spanner_from_properties (Translator_group *tg, SCM x)
196 SCM props = updated_grob_properties (tg, x);
197 return new Spanner (props);