]> git.donarmstrong.com Git - lilypond.git/blob - src/complexwalker.cc
release: 0.0.34
[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     Staff_column*c =ptr();
177
178     for (int i=0; i < c->commandreq_l_arr_.size(); i++) {
179         try_request(c->commandreq_l_arr_[i]);
180     }
181
182     for (int i=0; i < c->musicalreq_l_arr_.size(); i++) {
183         try_request(c->musicalreq_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         ptr()->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
259 void
260 Complex_walker::do_pre_move()
261 {
262     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
263         i->pre_move_processing();   
264     }
265     for (iter_top (group_reg_list_, j); j.ok(); j++) 
266         j->pre_move_processing();
267     local_key_reg_p_->pre_move_processing();
268     bar_reg_p_->pre_move_processing();
269     clef_reg_p_->pre_move_processing();
270     key_reg_p_->pre_move_processing();
271     meter_reg_p_->pre_move_processing();
272
273     ptr()->typeset_breakable_items(prebreak_item_p_arr_,
274                                    nobreak_item_p_arr_,
275                                    postbreak_item_p_arr_);
276 }
277
278 void
279 Complex_walker::do_post_move()
280 {
281     for (iter_top(voice_reg_list_,i); i.ok(); i++) {
282         i->post_move_processing();   
283     }
284     announce_info_arr_.set_size(0);
285     for (iter_top (group_reg_list_, j); j.ok(); j++) 
286         j->post_move_processing();
287     
288     local_key_reg_p_->post_move_processing();
289     bar_reg_p_->post_move_processing();
290     clef_reg_p_->post_move_processing();
291     key_reg_p_->post_move_processing();
292     meter_reg_p_->post_move_processing();
293
294 }
295
296 Array<Voice_registers*>
297 Complex_walker::get_voice_regs(Voice_group_registers* group_regs_l) const
298     return l_arr;
299 {
300     for (Assoc_iter<Voice*,Voice_group_registers*> i(voice_group_map_);
301          i.ok(); i++) {
302         if (i.val() == group_regs_l)
303             l_arr.push(find_voice_reg(i.key()));
304     }
305 }
306
307 void
308 Complex_walker::typeset_breakable_item(Item * pre_p , Item * nobreak_p,
309                                        Item * post_p)
310 {
311     if (pre_p)
312         prebreak_item_p_arr_.push(pre_p);
313     if (nobreak_p)
314         nobreak_item_p_arr_.push(nobreak_p);
315     if (post_p)
316         postbreak_item_p_arr_.push(post_p);
317 }