]> git.donarmstrong.com Git - lilypond.git/blob - lily/property-engraver.cc
baddf06bb6999e70cb79cbb886da892cefa0c98f
[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 ").ch_C(), errport);
122
123           scm_puts (origin->type_str_.ch_C(), errport);
124           scm_puts (".", errport);
125           
126           SCM name = e->get_elt_property ("meta");
127           name = scm_assoc (ly_symbol2scm ("name"), name);
128           scm_display (gh_cdr(name), errport);
129           scm_puts(" \\push #'",errport);
130           scm_write (elt_prop_sym,errport);
131           scm_puts ( " = #",errport);
132           scm_write (val, scm_current_error_port ());
133           scm_puts ("\n", errport);
134         }
135       else
136
137         /*
138             we don't print a warning if VAL == #f, because we would
139             get lots of warnings when we restore stuff to default, eg.
140
141             slurDash = #1 [...] slurDash = ##f
142
143             should not cause "type error: slurDash expects number not
144             boolean"
145
146         */
147         if (val != SCM_BOOL_F)
148           {                     // not the right type: error message.
149             SCM errport = scm_current_error_port ();
150             warning (_("Wrong type for property"));
151             scm_display (prop_sym, errport);
152             scm_puts (", type: ", errport);
153
154             SCM typefunc = scm_eval2 (ly_symbol2scm ("type-name"), SCM_EOL);
155             
156             scm_display (gh_call1 (typefunc, type_p), errport);
157             scm_puts (", value found: ", errport);
158             scm_write (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);