]> git.donarmstrong.com Git - lilypond.git/blob - lily/engraver.cc
Run grand replace for 2015.
[lilypond.git] / lily / engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
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.
10
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.
15
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/>.
18 */
19
20 #include "engraver.hh"
21
22 #include "context.hh"
23 #include "grob-properties.hh"
24 #include "international.hh"
25 #include "music.hh"
26 #include "paper-column.hh"
27 #include "score-engraver.hh"
28 #include "spanner.hh"
29 #include "stream-event.hh"
30 #include "warn.hh"
31
32 Engraver_group *
33 Engraver::get_daddy_engraver () const
34 {
35   return dynamic_cast<Engraver_group *> (get_daddy_translator ());
36 }
37
38 void
39 Engraver::announce_grob (Grob_info inf)
40 {
41   get_daddy_engraver ()->announce_grob (inf);
42 }
43
44 void
45 Engraver::announce_end_grob (Grob_info inf)
46 {
47   inf.start_end_ = STOP;
48   get_daddy_engraver ()->announce_grob (inf);
49 }
50
51 Grob_info
52 Engraver::make_grob_info (Grob *e, SCM cause)
53 {
54   /* TODO: Remove Music code when it's no longer needed */
55   if (Music *m = Music::unsmob (cause))
56     {
57       cause = m->to_event ()->unprotect ();
58     }
59   if (e->get_property ("cause") == SCM_EOL
60       && (Stream_event::is_smob (cause) || Grob::is_smob (cause)))
61     e->set_property ("cause", cause);
62
63   return Grob_info (this, e);
64 }
65
66 /*
67   CAUSE is the object (typically a Stream_event object)  that
68   was the reason for making E.
69 */
70 void
71 Engraver::announce_grob (Grob *e, SCM cause)
72 {
73   announce_grob (make_grob_info (e, cause));
74 }
75
76 /*
77   CAUSE is the object (typically a grob or stream-event object) that
78   was the reason for ending E.  */
79 void
80 Engraver::announce_end_grob (Grob *e, SCM cause)
81 {
82   announce_end_grob (make_grob_info (e, cause));
83 }
84
85 Engraver::Engraver ()
86 {
87 }
88
89 #ifndef NDEBUG
90 static SCM creation_callback = SCM_EOL;
91 LY_DEFINE (ly_set_grob_creation_callback, "ly:set-grob-creation-callback",
92            1, 0, 0, (SCM cb),
93            "Specify a procedure that will be called every time a new grob"
94            " is created.  The callback will receive as arguments the grob"
95            " that was created, the name of the C++ source file that caused"
96            " the grob to be created, and the corresponding line number in"
97            " the C++ source file.")
98 {
99   LY_ASSERT_TYPE (ly_is_procedure, cb, 1);
100
101   creation_callback = cb;
102
103   return SCM_UNSPECIFIED;
104 }
105 #endif
106
107 Grob *
108 Engraver::internal_make_grob (SCM symbol,
109                               SCM cause,
110                               char const * /* name */,
111                               char const *file,
112                               int line,
113                               char const *fun)
114 {
115 #ifdef NDEBUG
116   (void)file;
117   (void)line;
118   (void)fun;
119 #endif
120
121   SCM props = Grob_property_info (context (), symbol).updated ();
122
123   Grob *grob = 0;
124
125   SCM handle = scm_sloppy_assq (ly_symbol2scm ("meta"), props);
126   SCM klass = scm_cdr (scm_sloppy_assq (ly_symbol2scm ("class"), scm_cdr (handle)));
127
128   if (klass == ly_symbol2scm ("Item"))
129     grob = new Item (props);
130   else if (klass == ly_symbol2scm ("Spanner"))
131     grob = new Spanner (props);
132   else if (klass == ly_symbol2scm ("Paper_column"))
133     grob = new Paper_column (props);
134
135   assert (grob);
136   announce_grob (grob, cause);
137
138 #ifndef NDEBUG
139   if (ly_is_procedure (creation_callback))
140     scm_apply_0 (creation_callback,
141                  scm_list_n (grob->self_scm (), scm_from_locale_string (file),
142                              scm_from_int (line), scm_from_locale_string (fun), SCM_UNDEFINED));
143 #endif
144
145   return grob;
146 }
147
148 Item *
149 Engraver::internal_make_item (SCM x, SCM cause,
150                               char const *name,
151                               char const *file, int line, char const *fun)
152 {
153   Item *it = dynamic_cast<Item *> (internal_make_grob (x, cause, name, file, line, fun));
154   assert (it);
155   return it;
156 }
157
158 Paper_column *
159 Engraver::internal_make_column (SCM x, char const *name,
160                                 char const *file, int line, char const *fun)
161 {
162   return dynamic_cast<Paper_column *> (internal_make_grob (x, SCM_EOL, name, file, line, fun));
163 }
164
165 Spanner *
166 Engraver::internal_make_spanner (SCM x, SCM cause, char const *name,
167                                  char const *file, int line, char const *fun)
168 {
169   Spanner *sp = dynamic_cast<Spanner *> (internal_make_grob (x, cause, name, file, line, fun));
170   assert (sp);
171   return sp;
172 }
173
174 bool
175 ly_is_grob_cause (SCM obj)
176 {
177   return Grob::is_smob (obj) || Stream_event::is_smob (obj) || (obj == SCM_EOL);
178 }
179
180 #include "translator.icc"
181
182 ADD_TRANSLATOR (Engraver,
183                 /* doc */
184                 "Base class for engravers.  Does nothing, so it is not used.",
185
186                 /* create */
187                 "",
188
189                 /* read */
190                 "",
191
192                 /* write */
193                 ""
194                );
195