lilypond-0.0.32
[lilypond.git] / src / complexwalker.cc
blobba8253205b8b9c832c998061345c3bd83960476b
1 #include "associter.hh"
2 #include "script.hh"
3 #include "request.hh"
4 #include "voice.hh"
5 #include "clef.hh"
6 #include "pscore.hh"
7 #include "complexstaff.hh"
8 #include "debug.hh"
9 #include "keyitem.hh"
10 #include "clefitem.hh"
11 #include "voicegroup.hh"
12 #include "localkeyreg.hh"
13 #include "complexwalker.hh"
14 #include "misc.hh"
16 Rhythmic_grouping
17 parse_grouping(Array<Scalar> const &a)
19 Array<int> r;
20 Array<Moment> grouplen_arr;
21 for (int i= 0 ; i < a.size()/2; ) {
22 r.push(a[i++]);
23 grouplen_arr.push(Moment(1,(int) a[i++]));
25 Moment here =0;
27 Array<Rhythmic_grouping*> children;
28 for (int i=0; i < r.size(); i++) {
30 Moment last = here;
31 here += grouplen_arr[i] * Rational(r[i]);
32 children.push(
33 new Rhythmic_grouping(MInterval(last, here), r[i] ));
35 return Rhythmic_grouping(children);
38 void
39 Complex_walker::do_INTERPRET_command(Command*com_l)
41 Array<Scalar> args(com_l->args);
42 args.del(0);
43 String com = com_l->args[0];
45 if (com == "GROUPING") {
46 default_grouping = parse_grouping(args);
47 }else if (com == "NEWMEASURE") {
48 local_key_.reset(key_);
50 } else if (com == "KEY") {
52 if (col()->when() > Moment(0)) {
53 assert(!oldkey_undo);
54 oldkey_undo = new Array<int>( key_.oldkey_undo(args));
57 typesetkey = key_.read(args);
58 local_key_.reset(key_);
59 } else if (com == "CLEF") {
60 clef_.set_type(args[0]);
61 } else {
62 WARN << " ignoring INTERPRET command: " << com<< "\n";
66 void
67 Complex_walker::do_TYPESET_command(Command*com)
69 /* ignore these commands if non-default versions have been
70 processed. */
71 if (com->args[0] == "CURRENTKEY")
72 if (processed_key)
73 return;
74 else
75 com->args[0] = "KEY"; // urgh
77 if (com->args[0] == "CURRENTCLEF") {
78 if (processed_clef)
79 return;
81 if (com->args[0] == "BAR") {
83 if (processed_bar_priority > com->priority)
84 return;
85 else
86 processed_bar_priority = com->priority;
89 Item* i = staff()->get_TYPESET_item(com);
90 if (!i)
91 return;
93 if (com->args[0] == "KEY") {
94 ((Keyitem*) i)->read(clef_);
95 if (oldkey_undo) {
96 ((Keyitem*) i)->read(*oldkey_undo);
97 delete oldkey_undo;
98 oldkey_undo = 0;
100 processed_key = true;
102 ((Keyitem*) i)->read(typesetkey); // ugh
105 if (com->args[0] == "CLEF"||com->args[0] == "CURRENTCLEF") {
106 processed_clef =true;
107 Clef_item*c=(Clef_item*)i;
108 c->read(clef_);
109 c->change = (break_status != BREAK_POST - BREAK_PRE);
111 col()->typeset_item_directional(i, 1, break_status);
114 void
115 Complex_walker::announce_element(Staff_elem_info info)
117 info.group_regs_l_ = find_voice_group((Voice*)info.voice_l_);
118 announce_info_arr_.push(info);
121 void
122 Complex_walker::do_announces()
124 for (int i = 0; i < announce_info_arr_.size(); i++){
125 Staff_elem_info info = announce_info_arr_[i];
126 for (iter_top(voice_reg_list_,j); j.ok(); j++) {
127 j->acknowledge_element(info);
129 for (iter_top ( group_reg_list_, j); j.ok(); j++) {
130 j->acknowledge_element(info);
132 local_key_reg_.acknowledge_element(info);
136 Voice_registers *
137 Complex_walker::find_voice_reg(Voice*v_l)const
139 for (iter_top(voice_reg_list_, i); i.ok(); i++) {
140 if (i->voice_l_ == v_l)
141 return i;
143 return 0;
146 Voice_registers*
147 Complex_walker::get_voice_reg(Voice*v_l)
149 Voice_registers *regs_p=find_voice_reg(v_l);
150 if (regs_p)
151 return regs_p;
153 regs_p = new Voice_registers(this,v_l);
154 voice_reg_list_.bottom().add (regs_p);
155 return regs_p;
158 Voice_group_registers *
159 Complex_walker::find_voice_group(Voice* v_l)const
161 if (!voice_group_map_.elt_query(v_l))
162 return 0;
163 else return voice_group_map_[v_l];
166 Voice_group_registers *
167 Complex_walker::find_voice_group(const char *id)const
169 for (iter_top(group_reg_list_, i); i.ok(); i++)
170 if (i->group_id_str_ == id)
171 return i;
172 return 0;
176 Voice_group_registers *
177 Complex_walker::get_voice_group(Voice *v_l)
179 Voice_group_registers *group_p = find_voice_group(v_l);
180 if (group_p)
181 return group_p;
183 group_p = new Voice_group_registers(this);
184 group_reg_list_.bottom().add(group_p);
185 voice_group_map_[v_l] = group_p;
186 return group_p;
190 Voice_group_registers *
191 Complex_walker::get_voice_group(const char* id)
193 Voice_group_registers *group_p = find_voice_group(id);
194 if (group_p)
195 return group_p;
196 group_p = new Voice_group_registers(this,id);
197 group_reg_list_.bottom().add(group_p);
198 return group_p;
201 void
202 Complex_walker::do_change_group(Voice * v, String group_id_str)
204 voice_group_map_[v] = get_voice_group(group_id_str);
207 void
208 Complex_walker::try_request(Request*req)
210 bool b=false;
211 Voice *voice_l = req->elt_l_->voice_l_;
213 if (req->groupchange()) {
214 do_change_group(voice_l, req->groupchange()->newgroup_str_);
215 b = true;
216 } else if (Voice_registers::acceptable_request(req)) {
217 Voice_registers *vregs_l = get_voice_reg(voice_l);
218 b = vregs_l->try_request(req);
219 } else if (Voice_group_registers::acceptable_request(req)){
220 Voice_group_registers* reg_l = get_voice_group(voice_l);
221 b = reg_l->try_request(req);
224 if (!b)
225 warning("junking request: " + String(req->name()), req->defined_ch_c_l_m);
228 void
229 Complex_walker::process_requests()
231 Complex_column*c = col();
233 for (int i=0; i < c->first_l_arr_.size(); i++) {
234 try_request(c->first_l_arr_[i]);
237 for (int i=0; i < c->second_l_arr_.size(); i++) {
238 try_request(c->second_l_arr_[i]);
241 regs_process_requests();
242 do_announces();
245 void
246 Complex_walker::regs_process_requests()
248 for (iter_top(voice_reg_list_, j); j.ok(); j++) {
249 j->process_requests();
251 for (iter_top(group_reg_list_, j); j.ok(); j++)
252 j->process_requests();
254 local_key_reg_.process_request();
257 void
258 Complex_walker::typeset_element(Staff_elem *elem_p)
260 if (!elem_p)
261 return;
262 if (elem_p->spanner())
263 pscore_l_->typeset_spanner(elem_p->spanner(), staff()->pstaff_l_);
264 else
265 col()->typeset_item(elem_p->item());
268 Complex_walker::Complex_walker(Complex_staff*s)
269 : Staff_walker(s, s->pstaff_l_->pscore_l_),
270 local_key_reg_(this)
272 oldkey_undo = 0;
273 do_post_move();
276 Complex_staff*
277 Complex_walker::staff()
279 return (Complex_staff*) staff_l_;
282 Complex_column*
283 Complex_walker::col()
285 return (Complex_column*) *(*this);
288 void
289 Complex_walker::do_pre_move()
291 for (iter_top(voice_reg_list_,i); i.ok(); i++) {
292 i->pre_move_processing();
294 for (iter_top (group_reg_list_, j); j.ok(); j++)
295 j->pre_move_processing();
296 local_key_reg_.pre_move_processing();
299 void
300 Complex_walker::do_post_move()
302 processed_clef = false;
303 processed_key = false;
304 processed_bar_priority = 0;
306 for (iter_top(voice_reg_list_,i); i.ok(); i++) {
307 i->post_move_processing();
309 announce_info_arr_.set_size(0);
310 for (iter_top (group_reg_list_, j); j.ok(); j++)
311 j->post_move_processing();
312 local_key_reg_.post_move_processing();
315 Array<Voice_registers*>
316 Complex_walker::get_voice_regs(Voice_group_registers* group_regs_l) const
317 return l_arr;
319 for (Assoc_iter<Voice*,Voice_group_registers*> i(voice_group_map_); i.ok(); i++) {
320 if (i.val() == group_regs_l)
321 l_arr.push(find_voice_reg(i.key()));