]> git.donarmstrong.com Git - lilypond.git/blob - lily/key-engraver.cc
release: 1.3.55
[lilypond.git] / lily / key-engraver.cc
1 /*
2   key-engraver.cc -- implement Key_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7   */
8
9 #include "key-engraver.hh"
10 #include "key-item.hh"
11 #include "command-request.hh"
12 #include "local-key-engraver.hh"
13 #include "musical-request.hh"
14 #include "local-key-item.hh"
15 #include "bar.hh"
16 #include "timing-translator.hh"
17 #include "staff-symbol-referencer.hh"
18
19 /*
20   this is a large mess. Please clean this to use Basic properties and
21   Scheme data structs.
22  */
23
24 Key_engraver::Key_engraver ()
25 {
26   item_p_ = 0;
27   do_post_move_processing ();
28 }
29
30 bool
31 Key_engraver::key_changed_b () const
32 {
33   return keyreq_l_ ;
34 }
35
36 void
37 Key_engraver::create_key (bool def)
38 {
39   if (!item_p_) 
40     {
41       item_p_ = new Key_item ( get_property ("basicKeyProperties"));
42       
43       item_p_->set_elt_property ("c0-position", gh_int2scm (0));
44
45       // todo: put this in basic props.
46       item_p_->set_elt_property ("old-accidentals", SCM_EOL);
47       item_p_->set_elt_property ("new-accidentals", SCM_EOL);
48
49       Staff_symbol_referencer_interface st (item_p_);
50       st.set_interface ();
51       
52       if (key_.multi_octave_b_)
53         item_p_->set_elt_property ("multi-octave", gh_bool2scm (key_.multi_octave_b_));
54       
55       announce_element (Score_element_info (item_p_,keyreq_l_));
56       
57
58       for (int i = 0; i < accidental_idx_arr_.size(); i++) 
59         {
60           Musical_pitch m_l =accidental_idx_arr_[i];
61           int a =m_l.accidental_i_;      
62           if (key_.multi_octave_b_)
63             item_p_->add (m_l.steps (), a);
64           else
65             item_p_->add (m_l.notename_i_, a);
66         }
67
68       for (int i = 0 ; i < old_accidental_idx_arr_.size(); i++) 
69         {
70           Musical_pitch m_l =old_accidental_idx_arr_[i];
71           int a =m_l.accidental_i_;
72           if (key_.multi_octave_b_)
73             item_p_->add_old (m_l.steps  (), a);
74           else
75             item_p_->add_old (m_l.notename_i_, a);
76         }
77     }
78
79
80   if (!def)
81     item_p_->set_elt_property ("visibility-lambda",
82                                scm_eval (ly_symbol2scm  ("all-visible")));
83
84 }      
85
86
87 bool
88 Key_engraver::do_try_music (Music * req_l)
89 {
90   if (Key_change_req *kc = dynamic_cast <Key_change_req *> (req_l))
91     {
92       if (keyreq_l_)
93         warning (_ ("FIXME: key change merge"));
94       keyreq_l_ = kc;
95       read_req (keyreq_l_);
96       return true;
97     }   
98   return  false;
99 }
100
101 void
102 Key_engraver::acknowledge_element (Score_element_info info)
103 {
104   if (dynamic_cast <Clef_change_req *> (info.req_l_)) 
105     {
106       SCM c =  get_property ("createKeyOnClefChange");
107       if (to_boolean (c))
108         {
109           create_key (false);
110       
111         }
112     }
113   else if (dynamic_cast<Bar *> (info.elem_l_)
114            && accidental_idx_arr_.size ()) 
115     {
116       create_key (true);
117     }
118
119 }
120
121 void
122 Key_engraver::do_process_music ()
123 {
124   if (keyreq_l_) 
125     {
126       create_key (false);
127     }
128 }
129
130 void
131 Key_engraver::do_pre_move_processing ()
132
133   if (item_p_) 
134     {
135       typeset_element (item_p_);
136       item_p_ = 0;
137     }
138 }
139
140
141 /*
142   TODO.  Use properties; and this is too hairy.
143  */
144 void
145 Key_engraver::read_req (Key_change_req const * r)
146 {
147   if (!r->key_)
148     return;
149   
150   old_accidental_idx_arr_ = accidental_idx_arr_;
151   key_.clear ();
152   SCM prop = get_property ("keyOctaviation");
153
154   key_.multi_octave_b_ = to_boolean (prop);
155   
156   accidental_idx_arr_.clear ();
157
158   if (r->key_->ordinary_key_b_) 
159     {
160       int no_of_acc = r->key_->ordinary_accidentals_i ();
161
162       // Hmm, can't these be handled/constructed by Key_change_req?
163       if (no_of_acc < 0) 
164         {
165           int accidental = 6 ; // First accidental: bes
166           for ( ; no_of_acc < 0 ; no_of_acc++ ) 
167             {
168               Musical_pitch m;
169               m.accidental_i_ = -1;
170               m.notename_i_ = accidental;
171               if (key_.multi_octave_b_)
172                 key_.set (m);
173               else
174                 key_.set (m.notename_i_, m.accidental_i_);
175               accidental_idx_arr_.push (m);
176               
177               accidental = (accidental + 3) % 7 ;
178             }
179         }
180       else 
181         { 
182           int accidental = 3 ; // First accidental: fis
183           for ( ; no_of_acc > 0 ; no_of_acc-- ) 
184             {
185               Musical_pitch m;
186               m.accidental_i_ = 1;
187               m.notename_i_ = accidental;
188               if (key_.multi_octave_b_)
189                 key_.set (m);
190               else
191                 key_.set (m.notename_i_, m.accidental_i_);
192               accidental_idx_arr_.push (m);
193               
194               accidental = (accidental + 4) % 7 ;
195             }
196         }
197     }
198   else // Special key
199     {
200       for (int i = 0; i < r->key_->pitch_arr_.size (); i ++) 
201         {
202           Musical_pitch m_l =r->key_->pitch_arr_[i];
203           if (key_.multi_octave_b_)
204             key_.set (m_l);
205           else
206             key_.set (m_l.notename_i_, m_l.accidental_i_);
207           
208           accidental_idx_arr_.push (m_l);
209         }
210     }
211 }
212
213 void
214 Key_engraver::do_post_move_processing ()
215 {
216   keyreq_l_ = 0;
217   old_accidental_idx_arr_.clear ();
218 }
219
220 ADD_THIS_TRANSLATOR (Key_engraver);
221