]> git.donarmstrong.com Git - lilypond.git/blob - src/complexwalker.cc
c6478fbb236f78b8231b13d523bfcdc522ad74f1
[lilypond.git] / src / complexwalker.cc
1 /*
2   complexwalker.cc -- implement Complex_walker
3
4   source file of the LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "associter.hh"
10 #include "script.hh"
11 #include "musicalrequest.hh"
12 #include "voice.hh"
13 #include "pscore.hh"
14 #include "complexstaff.hh"
15 #include "debug.hh"
16 #include "voicegroup.hh"
17 #include "complexwalker.hh"
18 #include "misc.hh"
19 #include "commandrequest.hh"
20 #include "clefreg.hh"
21 #include "localkeyreg.hh"
22 #include "keyreg.hh"
23 #include "meterreg.hh"
24 #include "barreg.hh"
25
26
27 void
28 Complex_walker::announce_element(Staff_elem_info info)
29 {
30     info.group_regs_l_ = find_voice_group((Voice*)info.voice_l_);
31     announce_info_arr_.push(info);
32 }
33
34 void
35 Complex_walker::do_announces()
36 {
37     Request dummy_req;
38     for (int i = 0; i < announce_info_arr_.size(); i++){
39         Staff_elem_info info = announce_info_arr_[i];
40         if (!info.req_l_)
41             info.req_l_ = &dummy_req;
42         
43         for (iter_top(voice_reg_list_,j); j.ok(); j++) {
44             j->acknowledge_element(info);
45         }
46         for (iter_top ( group_reg_list_, j); j.ok(); j++) {
47             j->acknowledge_element(info);
48         }
49         bar_reg_p_->acknowledge_element(info);
50         clef_reg_p_->acknowledge_element(info);
51         key_reg_p_->acknowledge_element(info);
52         meter_reg_p_->acknowledge_element(info);
53         
54         local_key_reg_p_->acknowledge_element(info);
55     }
56 }
57
58 Voice_registers *
59 Complex_walker::find_voice_reg(Voice*v_l)const
60 {
61    for (iter_top(voice_reg_list_, i); i.ok(); i++) {
62         if (i->voice_l_ == v_l)
63             return i;
64    }
65    return 0;
66 }
67
68 Voice_registers*
69 Complex_walker::get_voice_reg(Voice*v_l)
70 {
71     Voice_registers *regs_p=find_voice_reg(v_l);
72     if (regs_p)
73         return regs_p;
74     
75     regs_p = new Voice_registers(this,v_l);
76     voice_reg_list_.bottom().add (regs_p);
77     return regs_p;
78 }
79
80 Voice_group_registers *
81 Complex_walker::find_voice_group(Voice* v_l)const
82 {
83     if (!voice_group_map_.elt_query(v_l))
84         return 0;
85     else return voice_group_map_[v_l];
86 }
87
88 Voice_group_registers *
89 Complex_walker::find_voice_group(const char *id)const
90 {
91     for (iter_top(group_reg_list_, i); i.ok(); i++)
92         if (i->group_id_str_ == id)
93             return i;
94     return 0;
95 }
96
97
98 Voice_group_registers *
99 Complex_walker::get_voice_group(Voice *v_l)
100 {
101     Voice_group_registers *group_p = find_voice_group(v_l);
102     if (group_p)
103         return group_p;
104     
105     group_p = new Voice_group_registers(this);
106     group_reg_list_.bottom().add(group_p);
107     voice_group_map_[v_l] = group_p;
108     return group_p;
109 }
110
111
112 Voice_group_registers *
113 Complex_walker::get_voice_group(const char* id)
114 {
115     Voice_group_registers *group_p = find_voice_group(id);
116     if (group_p)
117         return group_p;
118     group_p = new Voice_group_registers(this,id);
119     group_reg_list_.bottom().add(group_p);
120     return group_p;
121 }
122
123 void 
124 Complex_walker::do_change_group(Voice * v, String group_id_str)
125 {
126     voice_group_map_[v] = get_voice_group(group_id_str);
127 }
128
129 bool
130 Complex_walker::try_command_request(Nonmusical_req *req_l)
131 {
132     bool b=false;
133     Voice *voice_l = (Voice*)req_l->elt_l_->voice_l_; // ugh
134     if (req_l->groupchange()){
135         do_change_group(voice_l, req_l->groupchange()->newgroup_str_);
136         b|= true;
137     } else if(req_l->groupfeature()) {
138         Voice_group_registers* reg_l = get_voice_group(voice_l);
139         b |= reg_l->try_request(req_l);
140     } else {
141         if (!b)
142             b |= bar_reg_p_->try_request(req_l);
143         b |= clef_reg_p_->try_request(req_l);
144         if (!b) 
145             b |= key_reg_p_->try_request(req_l);
146         if (!b)
147             b |= meter_reg_p_->try_request(req_l);
148     }
149     return b;
150 }
151
152 void
153 Complex_walker::try_request(Request*req)
154 {
155     bool b=false;
156     Voice *voice_l = (Voice*)req->elt_l_->voice_l_; // ahh. This sux
157
158     if (req->nonmus()) {
159         b = try_command_request(req->nonmus());
160     } else if (Voice_registers::acceptable_request(req)) {
161         Voice_registers *vregs_l = get_voice_reg(voice_l);
162         b = vregs_l->try_request(req);
163     } else if (Voice_group_registers::acceptable_request(req)){
164         Voice_group_registers* reg_l = get_voice_group(voice_l);
165         b = reg_l->try_request(req);
166     } 
167
168     if (!b)
169         warning("junking request: "  + String(req->name()),
170                 req->defined_ch_c_l_);
171 }
172
173 void
174 Complex_walker::process_requests()
175 {
176     Complex_column*c = col();
177
178     for (int i=0; i < c->first_l_arr_.size(); i++) {
179         try_request(c->first_l_arr_[i]);
180     }
181
182     for (int i=0; i < c->second_l_arr_.size(); i++) {
183         try_request(c->second_l_arr_[i]);
184     }
185
186     regs_process_requests();
187     do_announces();
188 }
189
190 void
191 Complex_walker::regs_process_requests()
192 {
193     for (iter_top(voice_reg_list_, j); j.ok(); j++) {
194         j->process_requests();
195     }
196     for (iter_top(group_reg_list_, j); j.ok(); j++) 
197         j->process_requests();
198     
199     
200     bar_reg_p_->process_request();
201     clef_reg_p_->process_request();
202     key_reg_p_->process_request();
203     meter_reg_p_->process_request();
204     local_key_reg_p_->process_request();
205 }
206
207 void
208 Complex_walker::typeset_element(Staff_elem *elem_p)
209 {
210     if (!elem_p)
211         return;
212     if (elem_p->spanner())
213         pscore_l_->typeset_spanner(elem_p->spanner(), staff()->pstaff_l_);
214     else
215         col()->typeset_musical_item(elem_p->item()); 
216 }
217
218 Complex_walker::Complex_walker(Complex_staff*s)
219     : Staff_walker(s, s->pstaff_l_->pscore_l_)
220 {
221     local_key_reg_p_= new Local_key_register(this);
222     clef_reg_p_= new Clef_register(this);
223     key_reg_p_ = new Key_register(this);
224     bar_reg_p_ = new Bar_register(this);
225     meter_reg_p_ = new Meter_register(this);
226     
227     do_post_move();
228 }
229
230
231 Complex_walker::~Complex_walker()
232 {
233     delete local_key_reg_p_;
234     delete clef_reg_p_;
235     delete meter_reg_p_;
236     delete bar_reg_p_;
237     delete key_reg_p_;
238 }
239
240 int
241 Complex_walker::c0_position_i()const
242 {
243     return c0_position_i_;
244 }
245
246 void
247 Complex_walker::set_c0_position(int p)
248 {
249     c0_position_i_ =p;
250 }
251
252 Complex_staff*
253 Complex_walker::staff()
254 {
255     return (Complex_staff*) staff_l_;
256 }
257
258 Complex_column*
259 Complex_walker::col()
260 {
261     return (Complex_column*) *(*this);
262 }
263
264 void
265 Complex_walker::do_pre_move()
266 {
267     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
268         i->pre_move_processing();   
269     }
270     for (iter_top (group_reg_list_, j); j.ok(); j++) 
271         j->pre_move_processing();
272     local_key_reg_p_->pre_move_processing();
273     bar_reg_p_->pre_move_processing();
274     clef_reg_p_->pre_move_processing();
275     key_reg_p_->pre_move_processing();
276     meter_reg_p_->pre_move_processing();
277
278     col()->typeset_breakable_items(prebreak_item_p_arr_,
279                                    nobreak_item_p_arr_,
280                                    postbreak_item_p_arr_);
281 }
282
283 void
284 Complex_walker::do_post_move()
285 {
286     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
287         i->post_move_processing();   
288     }
289     announce_info_arr_.set_size(0);
290     for (iter_top (group_reg_list_, j); j.ok(); j++) 
291         j->post_move_processing();
292     
293     local_key_reg_p_->post_move_processing();
294     bar_reg_p_->post_move_processing();
295     clef_reg_p_->post_move_processing();
296     key_reg_p_->post_move_processing();
297     meter_reg_p_->post_move_processing();
298
299 }
300
301 Array<Voice_registers*>
302 Complex_walker::get_voice_regs(Voice_group_registers* group_regs_l) const
303     return l_arr;
304 {
305     for (Assoc_iter<Voice*,Voice_group_registers*> i(voice_group_map_);
306          i.ok(); i++) {
307         if (i.val() == group_regs_l)
308             l_arr.push(find_voice_reg(i.key()));
309     }
310 }
311
312 void
313 Complex_walker::typeset_breakable_item(Item * pre_p , Item * nobreak_p,
314                                        Item * post_p)
315 {
316     if (pre_p)
317         prebreak_item_p_arr_.push(pre_p);
318     if (nobreak_p)
319         nobreak_item_p_arr_.push(nobreak_p);
320     if (post_p)
321         postbreak_item_p_arr_.push(post_p);
322 }