]> git.donarmstrong.com Git - lilypond.git/blob - lily/property-engraver.cc
release: 1.5.19
[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--2001 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 "grob.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, Grob*, Translator_group *origin);
28
29 protected:
30   virtual void acknowledge_grob (Grob_info ei);
31   virtual void initialize ();
32   virtual void finalize ();
33 public:
34   ~Property_engraver ();
35   TRANSLATOR_DECLARATIONS(Property_engraver);
36 };
37
38
39
40 Property_engraver::Property_engraver ()
41 {
42   prop_dict_ = 0;
43 }
44 void
45 Property_engraver::finalize ()
46 {
47   
48 }
49
50 Property_engraver::~Property_engraver ()
51 {
52   if (prop_dict_)
53     scm_gc_unprotect_object (prop_dict_->self_scm ());
54 }
55
56 void
57 Property_engraver::initialize ()
58 {
59   prop_dict_ = new Scheme_hash_table;
60
61   SCM plist = get_property ("Generic_property_list");
62   for (; gh_pair_p (plist); plist = ly_cdr (plist))
63     {
64       SCM elt_props = ly_car (plist);
65       prop_dict_->set (ly_car (elt_props), ly_cdr (elt_props));
66     }
67 }
68
69 void
70 Property_engraver::acknowledge_grob (Grob_info i)
71 {
72  SCM ifs = i.grob_l_->get_grob_property ("interfaces");
73   SCM props;
74   for (; gh_pair_p (ifs); ifs = ly_cdr (ifs))
75     {      
76       if (prop_dict_->try_retrieve (ly_car (ifs), &props))
77         {
78           apply_properties (props,i.grob_l_, i.origin_trans_l_->daddy_trans_l_);
79         }
80     }
81
82   if (prop_dict_->try_retrieve (ly_symbol2scm ("all"), &props))
83     {
84       apply_properties (props, i.grob_l_, i.origin_trans_l_->daddy_trans_l_);
85     }
86 }
87
88
89 void
90 Property_engraver::apply_properties (SCM p, Grob *e, Translator_group*origin)
91 {
92   for (; gh_pair_p (p); p = ly_cdr (p))
93     {
94       /*
95         Try each property in order; earlier descriptions take
96         precedence over later ones, and we don't touch elt-properties if
97         they're already set.
98       */
99       
100       SCM entry = ly_car (p);
101       SCM prop_sym = ly_car (entry);
102       SCM type_p   = ly_cadr (entry);
103       SCM elt_prop_sym = ly_caddr (entry);
104
105       SCM preset = scm_assq (elt_prop_sym, e->mutable_property_alist_);
106       if (preset != SCM_BOOL_F)
107         continue;
108   
109       SCM val = internal_get_property (prop_sym);
110
111       if (val == SCM_EOL)
112         ;                       // Not defined in context.
113       else if (gh_apply (type_p, scm_list_n (val, SCM_UNDEFINED))
114                == SCM_BOOL_T)   // defined and  right type: do it
115         {
116           e->internal_set_grob_property (elt_prop_sym, val);
117
118           SCM meta = e->get_grob_property ("meta");
119           SCM name = scm_assoc (ly_symbol2scm ("name"), meta);
120           warning (_f ("`%s' is deprecated.  Use\n \\property %s.%s \\override #'%s = #%s",
121                        ly_symbol2string (prop_sym).ch_C (),
122                        origin->type_str_.ch_C (),
123                        ly_scm2string (ly_cdr (name)).ch_C (),
124                        ly_symbol2string (elt_prop_sym).ch_C (),
125                        ly_scm2string (ly_write2scm (val)).ch_C ()));
126         }
127       else
128
129         /*
130             we don't print a warning if VAL == (), because we would
131             get lots of warnings when we restore stuff to default, eg.
132
133             slurDash = #1 [...] slurDash = ()
134
135             should not cause "type error: slurDash expects number not
136             boolean
137
138         */
139         if (val != SCM_EOL)
140           {                     // not the right type: error message.
141             SCM errport = scm_current_error_port ();
142             SCM typefunc = scm_primitive_eval (ly_symbol2scm ("type-name"));
143             SCM type_name = gh_call1 (typefunc, type_p);
144             warning (_f ("Wrong type for property: %s, type: %s, value found: %s, type: %s",
145                          ly_symbol2string (prop_sym).ch_C (),
146                          ly_scm2string (type_name).ch_C (),
147                          ly_scm2string (ly_write2scm (val)).ch_C (),
148                          ly_scm2string (ly_type (val)).ch_C ()));
149             scm_puts ("\n", errport);
150           }
151     }
152 }
153
154
155 ENTER_DESCRIPTION(Property_engraver,
156 /* descr */       "This is a engraver that converts property settings into
157 back-end grob-property settings. Example: Voice.stemLength will set
158 #'length in all Stem objects.
159
160 Due to CPU and memory requirements, the use of this engraver is deprecated.",
161 /* creats*/       "",
162 /* acks  */       "grob-interface",
163 /* reads */       "Generic_property_list",
164 /* write */       "");