]> git.donarmstrong.com Git - lilypond.git/blob - lily/include/translator.icc
Fix off-by-one error in constrained-breaking.
[lilypond.git] / lily / include / translator.icc
1 /*
2   translator.icc -- declare Translator glue wiring.
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #ifndef TRANSLATOR_ICC
10 #define TRANSLATOR_ICC
11
12 #include "listener.hh"
13 #include "std-vector.hh"
14 #include "translator.hh"
15
16 /*
17   TODO: derive "foo-bar-interface" from Foo_bar classname.
18  */
19
20 /**
21    A macro to automate administration of translators.
22 */
23 #define ADD_THIS_TRANSLATOR(T)                                          \
24   translator_listener_record *T::listener_list_;                        \
25   SCM T::static_description_ = SCM_EOL;                                 \
26   static void _ ## T ## _adder ()                                       \
27   {                                                                     \
28     T *t = new T;                                                       \
29     T::static_description_ = t->static_translator_description ();       \
30     scm_permanent_object (T::static_description_);                      \
31     add_translator (t);                                                 \
32   }                                                                     \
33   SCM T::translator_description () const                                \
34   {                                                                     \
35     return static_description_;                                         \
36   }                                                                     \
37   ADD_GLOBAL_CTOR (_ ## T ## _adder);
38
39 #define ADD_TRANSLATOR(classname, desc, grobs, read, write)             \
40   Drul_array< vector<Acknowledge_information> > classname::acknowledge_static_array_drul_;      \
41   IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS (classname);                    \
42   ADD_THIS_TRANSLATOR (classname);                                      \
43   Engraver_void_function_engraver_grob_info                             \
44   classname::static_get_acknowledger (SCM sym)                          \
45   {                                                                     \
46     return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[START]);      \
47   }                                                                     \
48   Engraver_void_function_engraver_grob_info                             \
49   classname::static_get_end_acknowledger (SCM sym)                              \
50   {                                                                     \
51     return generic_get_acknowledger (sym, &acknowledge_static_array_drul_[STOP]);       \
52   }                                                                     \
53   SCM                                                                   \
54   classname::static_translator_description () const                     \
55   {                                                                     \
56     return Translator::static_translator_description (grobs, desc, listener_list_, read, write); \
57   }
58
59 #define IMPLEMENT_FETCH_PRECOMPUTABLE_METHODS(T)                        \
60   void                                                                  \
61   T::fetch_precomputable_methods (Translator_void_method_ptr ptrs[])    \
62   {                                                                     \
63     ptrs[START_TRANSLATION_TIMESTEP] =                                  \
64       ((Translator_void_method_ptr) & T::start_translation_timestep ==  \
65        (Translator_void_method_ptr) & Translator::start_translation_timestep) \
66       ? 0                                                               \
67       : (Translator_void_method_ptr) & T::start_translation_timestep;   \
68                                                                         \
69     ptrs[STOP_TRANSLATION_TIMESTEP] =                                   \
70       ((Translator_void_method_ptr) & T::stop_translation_timestep == (Translator_void_method_ptr) & Translator::stop_translation_timestep) \
71       ? 0                                                               \
72       : (Translator_void_method_ptr) & T::stop_translation_timestep;    \
73                                                                         \
74     ptrs[PROCESS_MUSIC] =                                               \
75       ((Translator_void_method_ptr) & T::process_music == (Translator_void_method_ptr) & Translator::process_music) \
76       ? 0                                                               \
77       : (Translator_void_method_ptr) & T::process_music;                \
78                                                                         \
79     ptrs[PROCESS_ACKNOWLEDGED] =                                        \
80       ((Translator_void_method_ptr) & T::process_acknowledged == (Translator_void_method_ptr) & Translator::process_acknowledged) \
81       ? 0                                                               \
82       : (Translator_void_method_ptr) & T::process_acknowledged;         \
83   }
84
85 void add_acknowledger (Engraver_void_function_engraver_grob_info ptr,
86                        char const *func_name,
87                        vector<Acknowledge_information> *ack_array);
88
89 Engraver_void_function_engraver_grob_info
90 generic_get_acknowledger (SCM sym,
91                           vector<Acknowledge_information> const *ack_array);
92
93 #define ADD_ACKNOWLEDGER(CLASS, NAME)                                   \
94   void CLASS ## NAME ## _ack_adder ()                                   \
95   {                                                                     \
96     add_acknowledger ((Engraver_void_function_engraver_grob_info) & CLASS::acknowledge_ ## NAME, #NAME, &CLASS::acknowledge_static_array_drul_[START]); \
97   }                                                                     \
98   ADD_SCM_INIT_FUNC (CLASS ## NAME ## _ack_adder_initclass, CLASS ## NAME ## _ack_adder);
99
100 #define ADD_END_ACKNOWLEDGER(CLASS, NAME)                                       \
101   void CLASS ## NAME ## _end_ack_adder ()                                       \
102   {                                                                     \
103     add_acknowledger ((Engraver_void_function_engraver_grob_info) & CLASS::acknowledge_end_ ## NAME, #NAME, &CLASS::acknowledge_static_array_drul_[STOP]); \
104   }                                                                     \
105   ADD_SCM_INIT_FUNC (CLASS ## NAME ## _end_ack_adder_initclass, CLASS ## NAME ## _end_ack_adder);
106
107 /*
108   Implement the method cl::listen_##m, and make it listen to stream 
109   events of class m.
110  */
111 #define IMPLEMENT_TRANSLATOR_LISTENER(cl, m)            \
112 void                                                    \
113 cl :: _internal_declare_ ## m ()                        \
114 {                                                       \
115   static translator_listener_record r;                  \
116   add_translator_listener (&listener_list_, &r, _get_ ## m ## _listener, #m); \
117 }                                                       \
118                                                         \
119 ADD_SCM_INIT_FUNC (cl ## _declare_event_ ## m, cl::_internal_declare_ ## m);    \
120                                                         \
121 Listener                                                \
122 cl :: _get_ ## m ## _listener (void *me)                \
123 {                                                       \
124   cl *obj = (cl *) me;                                  \
125   return obj->GET_LISTENER (_listen_scm_ ## m);         \
126 }                                                       \
127                                                         \
128 IMPLEMENT_LISTENER (cl, _listen_scm_ ## m)              \
129 void                                                    \
130 cl::_listen_scm_ ## m (SCM sev)                         \
131 {                                                       \
132   Stream_event *ev = unsmob_stream_event (sev);         \
133   protect_event (sev);                                  \
134   listen_ ## m (ev);                                    \
135 }
136
137 #endif /* TRANSLATOR_ICC */