LEFT | RIGHT |
1 #include "context.hh" | 1 #include "context.hh" |
2 #include "spanner.hh" | 2 #include "spanner.hh" |
3 #include "spanner-engraver.hh" | 3 #include "spanner-engraver.hh" |
4 #include "std-string.hh" | |
5 #include "std-vector.hh" | |
6 | 4 |
7 vector<cv_entry> | 5 Spanner_engraver::Spanner_engraver () |
8 Spanner_engraver::my_cv_entries () | 6 : filter_share_ (NULL), filter_id_ (SCM_EOL), is_manager_ (true), current_span
ner_ (NULL) |
9 { | 7 { |
10 vector<cv_entry> entries; | 8 } |
11 SCM my_context = context ()->self_scm (); | 9 |
12 SCM my_class = ly_symbol2scm (class_name ()); | 10 void Spanner_engraver::initialize () |
13 for (Context *c = context (); c != NULL; c = c->get_parent_context ()) | 11 { |
| 12 if (is_manager_) |
14 { | 13 { |
15 SCM s; | 14 // Can't set this in constructor |
16 if (!c->here_defined (ly_symbol2scm ("sharedSpanners"), &s)) | 15 filter_share_ = context (); |
17 continue; | |
18 | 16 |
19 for (; scm_is_pair (s); s = scm_cdr (s)) | 17 SCM key = scm_vector (scm_list_3 (ly_symbol2scm (class_name ()), |
20 { | 18 filter_share_->self_scm (), filter_id_))
; |
21 SCM clazz = scm_caaar (s); | 19 SCM spanner_engravers = context ()->get_property ("spannerEngravers"); |
22 SCM entry = scm_cdar (s); | 20 SCM instances = scm_assoc_ref (spanner_engravers, key); |
23 if (ly_is_equal (scm_c_vector_ref (entry, 0), my_context) | 21 instances = scm_is_pair (instances) |
24 && ly_is_equal (clazz, my_class)) | 22 ? scm_cons (self_scm (), instances) |
25 { | 23 : scm_list_1 (self_scm ()); |
26 entries.push_back (cv_entry (entry, c)); | 24 context ()->set_property ("spannerEngravers", |
27 } | 25 scm_assoc_set_x (spanner_engravers, key, instanc
es)); |
28 } | |
29 } | 26 } |
30 return entries; | 27 } |
| 28 |
| 29 Spanner * |
| 30 Spanner_engraver::internal_make_multi_spanner (SCM x, SCM cause, SCM share, SCM
id, |
| 31 char const *file, int line, char
const *fun) |
| 32 { |
| 33 Spanner *span = internal_make_spanner (x, cause, file, line, fun); |
| 34 span->set_property ("spanner-id", id); |
| 35 span->set_property ("spanner-share-context", share); |
| 36 span->set_property ("current-engraver", self_scm ()); |
| 37 |
| 38 current_spanner_ = span; |
| 39 |
| 40 add_shared_spanner (get_share_context (share), id, span); |
| 41 return span; |
| 42 } |
| 43 |
| 44 Spanner_engraver * |
| 45 Spanner_engraver::take_spanner (SCM share_context, SCM id) |
| 46 { |
| 47 Spanner *span = get_shared_spanner (get_share_context (share_context), id); |
| 48 if (!span) |
| 49 { |
| 50 current_spanner_ = NULL; |
| 51 return NULL; |
| 52 } |
| 53 |
| 54 Spanner_engraver *owner |
| 55 = unsmob<Spanner_engraver> (span->get_property ("current-engraver")); |
| 56 owner->current_spanner_ = NULL; |
| 57 current_spanner_ = span; |
| 58 span->set_property ("current-engraver", self_scm ()); |
| 59 |
| 60 return owner; |
| 61 } |
| 62 |
| 63 void |
| 64 Spanner_engraver::end_spanner (Spanner *span, SCM cause) |
| 65 { |
| 66 if (!scm_is_null (cause)) |
| 67 announce_end_grob (span, cause); |
| 68 |
| 69 SCM id = span->get_property ("spanner-id"); |
| 70 Context *share = get_share_context (span->get_property ("spanner-share-context
")); |
| 71 // TODO may be called multiple times: need to check? |
| 72 delete_shared_spanner (share, id); |
31 } | 73 } |
32 | 74 |
33 Context * | 75 Context * |
34 Spanner_engraver::get_share_context (SCM s) | 76 Spanner_engraver::get_share_context (SCM s) |
35 { | 77 { |
36 Context *share = find_context_above (context (), s); | 78 Context *share = find_context_above (context (), s); |
37 return (share == NULL) ? context () : share; | 79 return (share == NULL) ? context () : share; |
38 } | 80 } |
39 | 81 |
40 SCM | 82 Spanner * |
41 Spanner_engraver::get_cv_entry (Context *share_context, SCM spanner_id) | 83 Spanner_engraver::get_shared_spanner (Context *share, SCM spanner_id) |
42 { | 84 { |
43 SCM s; | 85 SCM shared_spanners; |
44 if (!share_context->here_defined (ly_symbol2scm ("sharedSpanners"), &s)) | 86 if (!share->here_defined (ly_symbol2scm ("sharedSpanners"), &shared_spanners)) |
45 return SCM_EOL; | 87 return NULL; |
46 | 88 |
47 return scm_assoc_ref (s, key (spanner_id)); | 89 SCM spanner_list = scm_assoc_ref (shared_spanners, key (spanner_id)); |
48 } | 90 if (scm_is_false (spanner_list) || !scm_is_pair (spanner_list)) |
| 91 return NULL; |
49 | 92 |
50 Spanner * | 93 if (scm_is_pair (scm_cdr (spanner_list))) |
51 Spanner_engraver::get_cv_entry_spanner (SCM entry) | 94 warning ("Requested one spanner when multiple present"); |
52 { | 95 |
53 SCM spanner_or_list = scm_c_vector_ref (entry, 1); | 96 return unsmob<Spanner> (scm_car (spanner_list)); |
54 if (scm_is_pair (spanner_or_list)) | |
55 { | |
56 warning ("Requested one spanner when multiple present"); | |
57 return unsmob<Spanner> (scm_car (spanner_or_list)); | |
58 } | |
59 return unsmob<Spanner> (spanner_or_list); | |
60 } | 97 } |
61 | 98 |
62 vector<Spanner *> | 99 vector<Spanner *> |
63 Spanner_engraver::get_cv_entry_spanners (SCM entry) | 100 Spanner_engraver::get_shared_spanners (Context *share, SCM spanner_id) |
64 { | 101 { |
65 vector<Spanner *> spanners; | 102 vector<Spanner *> spanners; |
66 SCM spanner_or_list = scm_c_vector_ref (entry, 1); | 103 SCM shared_spanners; |
67 if (scm_is_pair (spanner_or_list)) | 104 if (share->here_defined (ly_symbol2scm ("sharedSpanners"), &shared_spanners)) |
68 { | 105 { |
69 do | 106 SCM spanner_list = scm_assoc_ref (shared_spanners, key (spanner_id)); |
| 107 while (scm_is_pair (spanner_list)) |
70 { | 108 { |
71 spanners.push_back (unsmob<Spanner> (scm_car (spanner_or_list))); | 109 spanners.push_back (unsmob<Spanner> (scm_car (spanner_list))); |
72 spanner_or_list = scm_cdr (spanner_or_list); | 110 spanner_list = scm_cdr (spanner_list); |
73 } | 111 } |
74 while (scm_is_pair (spanner_or_list)); | |
75 } | 112 } |
76 else | 113 |
77 spanners.push_back (unsmob<Spanner> (spanner_or_list)); | |
78 return spanners; | 114 return spanners; |
79 } | 115 } |
80 | 116 |
81 string | 117 void |
82 Spanner_engraver::get_cv_entry_name (SCM entry) | 118 Spanner_engraver::delete_shared_spanner (Context *share, SCM spanner_id) |
83 { | 119 { |
84 return ly_scm2string (scm_c_vector_ref (entry, 2)); | 120 SCM shared_spanners; |
85 } | 121 if (share->here_defined (ly_symbol2scm ("sharedSpanners"), &shared_spanners)) |
86 | 122 share->set_property ("sharedSpanners", |
87 SCM | 123 scm_assoc_remove_x (shared_spanners, key (spanner_id)))
; |
88 Spanner_engraver::get_cv_entry_other (SCM entry) | |
89 { | |
90 return scm_c_vector_ref (entry, 3); | |
91 } | 124 } |
92 | 125 |
93 void | 126 void |
94 Spanner_engraver::set_cv_entry_other (Context *share_context, SCM spanner_id, | 127 Spanner_engraver::add_shared_spanner (Context *share, SCM spanner_id, Spanner *s
pan) |
95 SCM entry, SCM other) | |
96 { | 128 { |
97 scm_c_vector_set_x (entry, 3, other); | 129 SCM shared_spanners; |
98 set_cv_entry (share_context, spanner_id, entry); | 130 if (!share->here_defined (ly_symbol2scm ("sharedSpanners"), &shared_spanners)) |
| 131 shared_spanners = SCM_EOL; |
| 132 |
| 133 SCM spanner_list = scm_assoc_ref (shared_spanners, key (spanner_id)); |
| 134 spanner_list = scm_is_false (spanner_list) |
| 135 ? scm_list_1 (span->self_scm ()) // Create new lis
t |
| 136 : scm_cons (span->self_scm (), spanner_list); // Add spanner to
existing list |
| 137 |
| 138 share->set_property ("sharedSpanners", |
| 139 scm_assoc_set_x (shared_spanners, |
| 140 key (spanner_id), spanner_list)); |
99 } | 141 } |
100 | |
101 void | |
102 Spanner_engraver::set_cv_entry_context (Context *share_context, | |
103 SCM spanner_id, SCM entry) | |
104 { | |
105 scm_c_vector_set_x (entry, 0, context ()->self_scm ()); | |
106 set_cv_entry (share_context, spanner_id, entry); | |
107 } | |
108 | |
109 void | |
110 Spanner_engraver::delete_cv_entry (Context *share_context, SCM spanner_id) | |
111 { | |
112 SCM s; | |
113 if (!share_context->here_defined (ly_symbol2scm ("sharedSpanners"), &s)) | |
114 return; | |
115 | |
116 share_context->set_property ("sharedSpanners", | |
117 scm_assoc_remove_x (s, key (spanner_id))); | |
118 } | |
119 | |
120 void | |
121 Spanner_engraver::create_cv_entry (Context *share_context, SCM spanner_id, | |
122 Spanner *spanner, string name, SCM other) | |
123 { | |
124 create_cv_entry (share_context, spanner_id, spanner->self_scm (), name, other)
; | |
125 } | |
126 | |
127 void | |
128 Spanner_engraver::create_cv_entry (Context *share_context, SCM spanner_id, | |
129 vector<Spanner *> spanners, string name, SCM
other) | |
130 { | |
131 SCM spanner_list = SCM_EOL; | |
132 for (vsize i = spanners.size (); i--;) | |
133 spanner_list = scm_cons (spanners[i]->self_scm (), spanner_list); | |
134 create_cv_entry (share_context, spanner_id, spanner_list, name, other); | |
135 } | |
136 | |
137 void | |
138 Spanner_engraver::create_cv_entry (Context *share_context, SCM spanner_id, | |
139 SCM spanner_or_list, string name, SCM other) | |
140 { | |
141 SCM entry = scm_vector (scm_list_4 (context ()->self_scm (), | |
142 spanner_or_list, | |
143 ly_string2scm (name), | |
144 other)); | |
145 SCM s; | |
146 if (!share_context->here_defined (ly_symbol2scm ("sharedSpanners"), &s)) | |
147 s = SCM_EOL; | |
148 | |
149 share_context->set_property ("sharedSpanners", | |
150 scm_acons (key (spanner_id), entry, s)); | |
151 } | |
152 | |
153 void | |
154 Spanner_engraver::set_cv_entry (Context *share_context, SCM spanner_id, | |
155 SCM entry) | |
156 { | |
157 SCM s; | |
158 if (!share_context->here_defined (ly_symbol2scm ("sharedSpanners"), &s)) | |
159 s = SCM_EOL; | |
160 | |
161 share_context->set_property ("sharedSpanners", | |
162 scm_assoc_set_x (s, key (spanner_id), entry)); | |
163 } | |
LEFT | RIGHT |