]> git.donarmstrong.com Git - lilypond.git/blob - lily/property-engraver.cc
9877b430ecb83ce248c5734a78c3cc227f591eb6
[lilypond.git] / lily / property-engraver.cc
1 /*   
2   property-engraver.cc --  implement Property engraver
3   
4   source file of the GNU LilyPond music typesetter
5   
6   (c) 1999--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   
8  */
9
10 #include "lily-guile.hh"
11 #include "engraver.hh"
12 #include "dictionary.hh"
13 #include "score-element.hh"
14 #include "scm-hash.hh"
15 #include "translator-group.hh"
16
17 /*
18   JUNKME: should use pushproperty everywhere.
19   
20  */
21 class Property_engraver : public Engraver
22 {
23   /*
24     UGH. Junk Dictionary
25   */
26   Scheme_hash_table *prop_dict_;        // junkme
27   void apply_properties (SCM, Score_element*, Translator_group *origin);
28
29 protected:
30   virtual void acknowledge_element (Score_element_info ei);
31   virtual void do_creation_processing ();
32   virtual void do_removal_processing ();
33 public:
34   ~Property_engraver();
35   Property_engraver();
36   VIRTUAL_COPY_CONS(Translator);
37 };
38
39
40
41 Property_engraver::Property_engraver()
42 {
43   prop_dict_ = 0;
44 }
45 void
46 Property_engraver::do_removal_processing()
47 {
48   
49 }
50
51 Property_engraver::~Property_engraver ()
52 {
53   if (prop_dict_)
54     scm_unprotect_object (prop_dict_->self_scm ());
55 }
56
57 void
58 Property_engraver::do_creation_processing ()
59 {
60   prop_dict_ = new Scheme_hash_table;
61
62   SCM plist = get_property (ly_symbol2scm ("Generic_property_list"));
63   for (; gh_pair_p (plist); plist = gh_cdr (plist))
64     {
65       SCM elt_props = gh_car (plist);
66       prop_dict_->set (gh_car (elt_props), gh_cdr (elt_props));
67     }
68 }
69
70 void
71 Property_engraver::acknowledge_element (Score_element_info i)
72 {
73   SCM ifs = i.elem_l_->get_elt_property ("interfaces");
74   SCM props;
75   for (; gh_pair_p (ifs); ifs = gh_cdr (ifs))
76     {      
77       if (prop_dict_->try_retrieve (gh_car (ifs), &props))
78         {
79           apply_properties (props,i.elem_l_, i.origin_trans_l_->daddy_trans_l_);
80         }
81     }
82
83   if (prop_dict_->try_retrieve (ly_symbol2scm ("all"), &props))
84     {
85       apply_properties (props, i.elem_l_, i.origin_trans_l_->daddy_trans_l_);
86     }
87 }
88
89
90 void
91 Property_engraver::apply_properties (SCM p, Score_element *e, Translator_group*origin)
92 {
93   for (; gh_pair_p (p); p = gh_cdr (p))
94     {
95       /*
96         Try each property in order; earlier descriptions take
97         precedence over later ones, and we don't touch elt-properties if
98         they're already set.
99       */
100       
101       SCM entry = gh_car (p);
102       SCM prop_sym = gh_car (entry);
103       SCM type_p   = gh_cadr (entry);
104       SCM elt_prop_sym = gh_caddr (entry);
105
106       SCM preset = scm_assq(elt_prop_sym, e->mutable_property_alist_);
107       if (preset != SCM_BOOL_F)
108         continue;
109   
110       SCM val = get_property (prop_sym);
111
112       if (val == SCM_UNDEFINED)
113         ;                       // Not defined in context.
114       else if (gh_apply (type_p, scm_listify (val, SCM_UNDEFINED))
115                == SCM_BOOL_T)   // defined and  right type: do it
116         {
117           e->set_elt_property (elt_prop_sym, val);
118
119           SCM errport = scm_current_error_port ();
120           scm_display (prop_sym, errport);
121           scm_puts (" is deprecated. Use\n \\property ", errport);
122
123           SCM name = e->get_elt_property ("name");
124           scm_puts (origin->type_str_.ch_C(), errport);
125           scm_puts (".", errport);
126           
127           scm_display (name, errport);
128           scm_puts(" \\push #'",errport);
129           scm_display (elt_prop_sym,errport);
130           scm_puts ( " = #",errport);
131           if (gh_string_p (val))
132             scm_puts ("\"", errport);
133           scm_display (val, scm_current_error_port ());
134           if (gh_string_p (val))
135             scm_puts ("\"", errport);
136           scm_puts ("\n", errport);
137         }
138       else
139
140         /*
141             we don't print a warning if VAL == #f, because we would
142             get lots of warnings when we restore stuff to default, eg.
143
144             slurDash = #1 [...] slurDash = ##f
145
146             should not cause "type error: slurDash expects number not
147             boolean"
148
149         */
150         if (val != SCM_BOOL_F)
151           {                     // not the right type: error message.
152             SCM errport = scm_current_error_port ();
153             warning (_("Wrong type for property"));
154             scm_display (prop_sym, errport);
155             scm_puts (", type predicate: ", errport);
156             scm_display (type_p, errport);
157             scm_puts (", value found: ", errport);
158             scm_display (val, errport);
159             scm_puts (" type: ", errport);
160             scm_display (ly_type (val), errport);
161             scm_puts ("\n", errport);
162           }
163     }
164 }
165
166 ADD_THIS_TRANSLATOR(Property_engraver);