]> git.donarmstrong.com Git - lilypond.git/blob - lily/engraver-group-engraver.cc
* lily/context.cc (where_defined): also assign value in
[lilypond.git] / lily / engraver-group-engraver.cc
1 /*
2   engraver-group-engraver.cc -- implement Engraver_group_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "engraver-group-engraver.hh"
10
11 #include "warn.hh"
12 #include "paper-score.hh"
13 #include "grob.hh"
14 #include "context.hh"
15 #include "translator-dispatch-list.hh"
16
17 void
18 Engraver_group_engraver::announce_grob (Grob_info info)
19 {
20   announce_infos_.push (info);
21
22   Engraver_group_engraver * dad_eng =
23     context_->get_parent_context ()
24     ? dynamic_cast<Engraver_group_engraver*> (context_->get_parent_context ()->implementation ())
25     : 0;
26   if (dad_eng)
27     dad_eng->announce_grob (info);
28 }
29
30 void
31 Engraver_group_engraver::acknowledge_grobs ()
32 {
33   if (!announce_infos_.size ())
34     return;
35
36   SCM name_sym = ly_symbol2scm ("name");
37   SCM meta_sym = ly_symbol2scm ("meta");
38
39   for (int j = 0; j < announce_infos_.size (); j++)
40     {
41       Grob_info info = announce_infos_[j];
42
43       SCM meta = info.grob ()->internal_get_property (meta_sym);
44       SCM nm = scm_assoc (name_sym, meta);
45       if (scm_is_pair (nm))
46         nm = scm_cdr (nm);
47       else
48         continue;
49
50       SCM acklist = scm_hashq_ref (acknowledge_hash_table_, nm, SCM_BOOL_F);
51       Engraver_dispatch_list *dispatch
52         = Engraver_dispatch_list::unsmob (acklist);
53
54       if (acklist == SCM_BOOL_F)
55         {
56           SCM ifaces
57             = scm_cdr (scm_assoc (ly_symbol2scm ("interfaces"), meta));
58           acklist = Engraver_dispatch_list::create (get_simple_trans_list (),
59                                                     ifaces);
60
61           dispatch
62             = Engraver_dispatch_list::unsmob (acklist);
63
64           scm_hashq_set_x (acknowledge_hash_table_, nm, acklist);
65         }
66
67
68       if (dispatch)
69         {
70           dispatch->apply (info);
71         }
72     }
73 }
74
75 /*
76   Ugh. This is slightly expensive. We could/should cache the value of
77   the group count?
78 */
79 int
80 Engraver_group_engraver::pending_grob_count () const
81 {
82   int count = announce_infos_.size ();
83   for (SCM s = context_->children_contexts ();
84        scm_is_pair (s); s = scm_cdr (s))
85     {
86       Context *c = unsmob_context (scm_car (s));
87       Engraver_group_engraver *group
88         = dynamic_cast<Engraver_group_engraver *> (c->implementation ());
89
90       if (group)
91         count += group->pending_grob_count ();
92     }
93   return count;
94 }
95
96 void
97 Engraver_group_engraver::do_announces ()
98 {
99   do
100     {
101       for (SCM s = context ()->children_contexts ();
102            scm_is_pair (s); s = scm_cdr (s))
103         {
104           Context *c = unsmob_context (scm_car (s));
105           Engraver_group_engraver *group
106             = dynamic_cast<Engraver_group_engraver *> (c->implementation ());
107           if (group)
108             group->do_announces ();
109         }
110
111       while (1)
112         {
113           precomputed_translator_foreach (PROCESS_ACKNOWLEDGED);
114           if (announce_infos_.size () == 0)
115             break;
116
117           acknowledge_grobs ();
118           announce_infos_.clear ();
119         }
120     }
121   while (pending_grob_count () > 0);
122 }
123
124
125 Engraver_group_engraver::Engraver_group_engraver ()
126 {
127   acknowledge_hash_table_ = SCM_EOL;
128   acknowledge_hash_table_ = scm_c_make_hash_table (61);
129 }
130
131 #include "translator.icc"
132
133 ADD_TRANSLATOR_GROUP (Engraver_group_engraver,
134                       /* descr */ "A group of engravers taken together",
135                       /* creats*/ "",
136                       /* accepts */ "",
137                       /* reads */ "",
138                       /* write */ "");
139
140
141
142 void
143 Engraver_group_engraver::derived_mark () const
144 {
145   scm_gc_mark (acknowledge_hash_table_);
146 }