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