1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3 
4   Copyright (C) 2002--2021 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 "music-wrapper-iterator.hh"
21 
22 #include "context.hh"
23 #include "input.hh"
24 #include "international.hh"
25 #include "music.hh"
26 #include "warn.hh"
27 
28 using std::string;
29 
30 class Context_specced_music_iterator final : public Music_wrapper_iterator
31 {
32 public:
33   DECLARE_SCHEME_CALLBACK (constructor, ());
34 
35 protected:
36   void create_contexts () override;
37 };
38 
39 void
create_contexts()40 Context_specced_music_iterator::create_contexts ()
41 {
42   // Change context in the wrapper before creating contexts for the wrapped
43   // iterators.
44 
45   SCM ct = get_property (get_music (), "context-type");
46 
47   string c_id;
48   SCM ci = get_property (get_music (), "context-id");
49   if (scm_is_string (ci))
50     c_id = ly_scm2string (ci);
51   SCM ops = get_property (get_music (), "property-operations");
52   Direction dir
53     = from_scm (get_property (get_music (), "search-direction"), CENTER);
54 
55   Context *a = 0;
56 
57   if (from_scm<bool> (get_property (get_music (), "create-new")))
58     {
59       a = get_own_context ()->create_unique_context (dir, ct, c_id, ops);
60       if (!a)
61         {
62           warning (_f ("cannot create context: %s",
63                        Context::diagnostic_id (ct, c_id).c_str ()));
64         }
65     }
66   else
67     {
68       a = get_own_context ()->find_create_context (dir, ct, c_id, ops);
69       // Warnings in regression tests would be pretty common if we didn't
70       // ignore them for DOWN.
71       //
72       // TODO: Not warning about a failure in DOWN mode smells funny.  It
73       // suggests that the fallback (remaining in the current context) is a
74       // fully acceptable alternative (from the perspective of the end user) in
75       // all cases; however, that seems unlikely.  But if this is the desired
76       // behavior for DOWN mode, should we do it for UP too?
77       if (!a && (dir != DOWN))
78         {
79           warning (_f ("cannot find or create context: %s",
80                        Context::diagnostic_id (ct, c_id).c_str ()));
81         }
82     }
83 
84   if (a)
85     set_own_context (a);
86 
87   Music_wrapper_iterator::create_contexts ();
88 }
89 
90 IMPLEMENT_CTOR_CALLBACK (Context_specced_music_iterator);
91