2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include <algorithm> // for reverse
22 #include "paper-column.hh"
23 #include "output-def.hh"
24 #include "side-position-interface.hh"
25 #include "engraver.hh"
27 #include "grob-array.hh"
28 #include "stream-event.hh"
30 #include "translator.icc"
33 TODO: detect the top staff (stavesFound), and acknowledge staff-group
34 system-start-delims. If we find these, and the top staff is in the
35 staff-group, add padding to the bar number.
37 class Bar_number_engraver : public Engraver
41 int alternative_starting_bar_number_;
42 int alternative_number_;
43 int alternative_number_increment_;
44 Stream_event *alternative_event_;
47 void stop_translation_timestep ();
48 DECLARE_TRANSLATOR_LISTENER (alternative);
49 DECLARE_ACKNOWLEDGER (break_alignment);
50 void process_music ();
52 TRANSLATOR_DECLARATIONS (Bar_number_engraver);
55 IMPLEMENT_TRANSLATOR_LISTENER (Bar_number_engraver, alternative);
57 Bar_number_engraver::listen_alternative (Stream_event *ev)
59 if (alternative_event_)
62 alternative_event_ = ev;
63 int current_barnumber = robust_scm2int (get_property ("currentBarNumber"), 0);
64 Direction alternative_dir = robust_scm2dir (ev->get_property ("alternative-dir"), CENTER);
65 bool make_alternative = get_property ("alternativeNumberingStyle") == ly_symbol2scm ("numbers")
66 || get_property ("alternativeNumberingStyle") == ly_symbol2scm ("numbers-with-letters");
70 if we're starting the first alternative, we set the starting
71 bar number to the current bar number
73 if (alternative_dir == LEFT)
74 alternative_starting_bar_number_ = current_barnumber;
77 if the alternative is not the last one, we send the
78 current bar number back to the alternative bar number.
80 if (alternative_dir < RIGHT)
81 current_barnumber = alternative_starting_bar_number_;
83 context ()->set_property ("currentBarNumber", scm_from_int (current_barnumber));
88 int_pow (int n, int i)
94 return int_pow (n * n, i - 1);
98 Bar_number_engraver::process_music ()
100 SCM wb = get_property ("whichBar");
102 if (scm_is_string (wb))
104 Moment mp (robust_scm2moment (get_property ("measurePosition"), Moment (0)));
105 if (mp.main_part_ == Rational (0))
107 SCM bn = get_property ("currentBarNumber");
108 SCM proc = get_property ("barNumberVisibility");
109 if (scm_is_number (bn) && ly_is_procedure (proc)
110 && to_boolean (scm_call_1 (proc, bn)))
113 SCM alternative_style = get_property ("alternativeNumberingStyle");
114 string text_tag = "";
115 if (alternative_style == ly_symbol2scm ("numbers-with-letters"))
117 if (alternative_event_)
119 Direction alternative_dir = robust_scm2dir (alternative_event_->get_property ("alternative-dir"), RIGHT);
120 switch (alternative_dir)
123 alternative_number_ = 0;
128 alternative_number_ = INT_MIN;
133 alternative_number_ += alternative_number_increment_;
135 alternative_number_increment_ = robust_scm2int (alternative_event_->get_property ("alternative-increment"), 1);
137 if (alternative_number_ >= 0)
139 string alphabet = "abcdefghijklmnopqrstuvwxyz";
142 int scratch = alternative_number_;
143 while (running_sum <= alternative_number_)
146 running_sum += int_pow (26, power);
148 scratch += int_pow (26, power) - running_sum;
149 for (int i = power; i--;)
150 text_tag += alphabet.at ((scratch / int_pow (26, i)) % 26);
156 scm_string_concatenate (scm_list_2 (scm_number_to_string (bn, scm_from_int (10)),
157 ly_string2scm (text_tag))));
163 Bar_number_engraver::Bar_number_engraver ()
166 alternative_starting_bar_number_ = 0;
167 alternative_number_increment_ = 0;
168 alternative_number_ = INT_MIN;
169 alternative_event_ = 0;
173 Bar_number_engraver::acknowledge_break_alignment (Grob_info inf)
175 Grob *s = inf.grob ();
177 && dynamic_cast<Item *> (s))
179 text_->set_parent (s, X_AXIS);
184 Bar_number_engraver::stop_translation_timestep ()
186 alternative_event_ = 0;
189 text_->set_object ("side-support-elements",
190 grob_list_to_grob_array (get_property ("stavesFound")));
196 Bar_number_engraver::create_items ()
201 text_ = make_item ("BarNumber", SCM_EOL);
204 ADD_ACKNOWLEDGER (Bar_number_engraver, break_alignment);
206 ADD_TRANSLATOR (Bar_number_engraver,
208 "A bar number is created whenever @code{measurePosition} is"
209 " zero and when there is a bar line (i.e., when"
210 " @code{whichBar} is set). It is put on top of all staves,"
211 " and appears only at the left side of the staff. The staves"
212 " are taken from @code{stavesFound}, which is maintained by"
213 " @ref{Staff_collecting_engraver}.",
222 "barNumberVisibility "
223 "alternativeNumberingStyle ",