X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fdispatcher.cc;h=b91b4fa5e935f15120e070b4cbf6111cd41d7816;hb=cc29cb407317df1e50ab28449b4c0ba7c24a579e;hp=c6fedb23741f6b050dd4dffe2768e6bc3fc62727;hpb=2a8dcc4faa8a16229774d3414eedbf46feceac84;p=lilypond.git diff --git a/lily/dispatcher.cc b/lily/dispatcher.cc index c6fedb2374..b91b4fa5e9 100644 --- a/lily/dispatcher.cc +++ b/lily/dispatcher.cc @@ -1,23 +1,30 @@ /* - dispatcher.cc -- implement Dispatcher + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2005--2010 Erik Sandberg - (c) 2005-2006 Erik Sandberg + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "dispatcher.hh" +#include "input.hh" #include "international.hh" #include "ly-smobs.icc" -#include "stream-event.hh" #include "warn.hh" -// ES todo: move to lily-guile.hh -SCM appendable_list (); -void appendable_list_append (SCM l, SCM elt); - IMPLEMENT_SMOBS (Dispatcher); -IMPLEMENT_TYPE_P (Dispatcher, "dispatcher"); +IMPLEMENT_TYPE_P (Dispatcher, "ly:dispatcher?"); IMPLEMENT_DEFAULT_EQUAL_P (Dispatcher); Dispatcher::~Dispatcher () @@ -31,7 +38,9 @@ Dispatcher::Dispatcher () dispatchers_ = SCM_EOL; listen_classes_ = SCM_EOL; smobify_self (); - listeners_ = scm_c_make_hash_table (0); +// TODO: use resizable hash (guile 1.8) +// listeners_ = scm_c_make_hash_table (0); + listeners_ = scm_c_make_hash_table (17); priority_count_ = 0; } @@ -70,11 +79,16 @@ Dispatcher::dispatch (SCM sev) SCM class_symbol = ev->get_property ("class"); if (!scm_symbol_p (class_symbol)) { - warning (_f ("Unknown event class %s", ly_symbol2string (class_symbol).c_str ())); + warning (_ ("Event class should be a symbol")); return; } SCM class_list = scm_call_1 (ly_lily_module_constant ("ly:make-event-class"), class_symbol); + if (!scm_is_pair (class_list)) + { + ev->origin ()->warning (_f ("Unknown event class %s", ly_symbol2string (class_symbol).c_str ())); + return; + } bool sent = false; int num_classes = scm_ilength (class_list); @@ -97,10 +111,10 @@ Dispatcher::dispatch (SCM sev) */ struct { int prio; SCM list; } lists[num_classes+1]; int i = 0; - for (SCM cl = class_list; scm_is_pair(cl); cl = scm_cdr (cl)) + for (SCM cl = class_list; scm_is_pair (cl); cl = scm_cdr (cl)) { SCM list = scm_hashq_ref (listeners_, scm_car (cl), SCM_EOL); - if (!scm_is_pair(list)) + if (!scm_is_pair (list)) num_classes--; else { @@ -138,17 +152,19 @@ Dispatcher::dispatch (SCM sev) } // go to the next listener; bubble-sort the class list. SCM next = scm_cdr (lists[0].list); - if (!scm_is_pair(next)) + if (!scm_is_pair (next)) num_classes--; - int prio = (scm_is_pair(next)) ? scm_to_int (scm_caar (next)) : INT_MAX; + int prio = (scm_is_pair (next)) ? scm_to_int (scm_caar (next)) : INT_MAX; for (i = 0; prio > lists[i+1].prio; i++) lists[i] = lists[i+1]; lists[i].prio = prio; lists[i].list = next; } +/* TODO: Uncomment. if (!sent) warning (_f ("Junking event: %s", ly_symbol2string (class_symbol).c_str ())); +*/ } void @@ -167,10 +183,11 @@ inline void Dispatcher::internal_add_listener (Listener l, SCM ev_class, int priority) { SCM list = scm_hashq_ref (listeners_, ev_class, SCM_EOL); - if (list == SCM_EOL) + if (!scm_is_pair (list)) { - /* Register with all dispatchers. */ - for (SCM disp = dispatchers_; scm_is_pair(disp); disp = scm_cdr (disp)) + /* Tell all dispatchers that we listen to, that we want to hear ev_class + events */ + for (SCM disp = dispatchers_; scm_is_pair (disp); disp = scm_cdr (disp)) { int priority = scm_to_int (scm_cdar (disp)); Dispatcher *d = unsmob_dispatcher (scm_caar (disp)); @@ -179,7 +196,7 @@ Dispatcher::internal_add_listener (Listener l, SCM ev_class, int priority) listen_classes_ = scm_cons (ev_class, listen_classes_); } SCM entry = scm_cons (scm_int2num (priority), l.smobbed_copy ()); - list = scm_merge_x (list, scm_list_1 (entry), ly_lily_module_constant ("car<")); + list = scm_merge (list, scm_list_1 (entry), ly_lily_module_constant ("car<")); scm_hashq_set_x (listeners_, ev_class, list); } @@ -199,23 +216,24 @@ Dispatcher::remove_listener (Listener l, SCM ev_class) SCM dummy = scm_cons (SCM_EOL, list); SCM e = dummy; - while (scm_is_pair(scm_cdr (e))) + while (scm_is_pair (scm_cdr (e))) if (*unsmob_listener (scm_cdadr (e)) == l && first) { - scm_set_cdr_x (e, scm_cddr(e)); + scm_set_cdr_x (e, scm_cddr (e)); first = false; break; } else e = scm_cdr (e); list = scm_cdr (dummy); + scm_hashq_set_x (listeners_, ev_class, list); if (first) warning ("Attempting to remove nonexisting listener."); - else if (list == SCM_EOL) + else if (!scm_is_pair (list)) { /* Unregister with all dispatchers. */ - for (SCM disp = dispatchers_; disp != SCM_EOL; disp = scm_cdr (disp)) + for (SCM disp = dispatchers_; scm_is_pair (disp); disp = scm_cdr (disp)) { Dispatcher *d = unsmob_dispatcher (scm_caar (disp)); d->remove_listener (GET_LISTENER (dispatch), ev_class); @@ -240,7 +258,7 @@ Dispatcher::register_as_listener (Dispatcher *disp) dispatchers_ = scm_acons (disp->self_scm (), scm_int2num (priority), dispatchers_); Listener list = GET_LISTENER (dispatch); - for (SCM cl = listen_classes_; cl != SCM_EOL; cl = scm_cdr (cl)) + for (SCM cl = listen_classes_; scm_is_pair (cl); cl = scm_cdr (cl)) { disp->internal_add_listener (list, scm_car (cl), priority); } @@ -252,9 +270,9 @@ Dispatcher::unregister_as_listener (Dispatcher *disp) { dispatchers_ = scm_assq_remove_x (dispatchers_, disp->self_scm ()); - Listener list = GET_LISTENER (dispatch); - for (SCM cl = listen_classes_; cl != SCM_EOL; cl = scm_cdr (cl)) + Listener listener = GET_LISTENER (dispatch); + for (SCM cl = listen_classes_; scm_is_pair (cl); cl = scm_cdr (cl)) { - disp->remove_listener (list, scm_car (cl)); + disp->remove_listener (listener, scm_car (cl)); } }