The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
handlers.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * The structure that tracks WML event handlers.
18  * (Typically, handlers are defined by [event] tags.)
19  */
20 
21 #include "global.hpp"
22 #include "handlers.hpp"
23 #include "manager.hpp"
24 #include "manager_impl.hpp"
25 #include "menu_item.hpp"
26 #include "pump.hpp"
27 
28 #include "formula/string_utils.hpp"
29 #include "game_data.hpp"
30 #include "log.hpp"
31 #include "reports.hpp"
34 #include "soundsource.hpp"
35 #include "util.hpp"
36 
37 #include <boost/unordered_map.hpp>
38 #include <iostream>
39 
40 
41 static lg::log_domain log_engine("engine");
42 #define DBG_NG LOG_STREAM(debug, log_engine)
43 #define LOG_NG LOG_STREAM(info, log_engine)
44 #define WRN_NG LOG_STREAM(warn, log_engine)
45 
46 static lg::log_domain log_event_handler("event_handler");
47 #define DBG_EH LOG_STREAM(debug, log_event_handler)
48 
49 
50 // This file is in the game_events namespace.
51 namespace game_events {
52 
53 /* ** handler_list::iterator ** */
54 
55 /**
56  * Dereference.
57  * If the current element has become invalid, we will increment first.
58  */
60 {
61  // Check for an available handler.
62  while ( iter_.derefable() ) {
63  // Handler still accessible?
64  if ( handler_ptr lock = iter_->lock() )
65  return lock;
66  else
67  // Remove the now-defunct entry.
69  }
70 
71  // End of the list.
72  return handler_ptr();
73 }
74 
75 
76 /* ** event_handler ** */
77 
78 event_handler::event_handler(const config &cfg, bool imi, handler_vec::size_type index, manager & man)
79  : first_time_only_(cfg["first_time_only"].to_bool(true))
80  , is_menu_item_(imi)
81  , index_(index)
82  , man_(&man)
83  , cfg_(cfg)
84 {}
85 
86 /**
87  * Disables *this, removing it from the game.
88  * (Technically, the handler is only removed once no one is hanging on to a
89  * handler_ptr to *this. So be careful how long they persist.)
90  *
91  * WARNING: *this may be destroyed at the end of this call, unless
92  * the caller maintains a handler_ptr to this.
93  */
95 {
96  assert(man_);
97  assert(man_->event_handlers_);
98  // Handlers must have an index after they're created.
99  assert ( index_ < man_->event_handlers_->size() );
100  // Disable this handler.
102 }
103 
104 /**
105  * Handles the queued event, according to our WML instructions.
106  * WARNING: *this may be destroyed at the end of this call, unless
107  * the caller maintains a handler_ptr to this.
108  *
109  * @param[in] event_info Information about the event that needs handling.
110  * @param[in,out] handler_p The caller's smart pointer to *this. It may be
111  * reset() during processing.
112  */
113 void event_handler::handle_event(const queued_event& event_info, handler_ptr& handler_p, game_lua_kernel & lk)
114 {
115  // We will need our config after possibly self-destructing. Make a copy now.
116  // TODO: instead of copying possibly huge config objects we should use shared things and only increase a refcount here.
117  vconfig vcfg(cfg_, true);
118 
119  if (is_menu_item_) {
120  DBG_NG << cfg_["name"] << " will now invoke the following command(s):\n" << cfg_;
121  }
122 
123  if (first_time_only_)
124  {
125  // Disable this handler.
126  disable();
127  // Also remove our caller's hold on us.
128  handler_p.reset();
129  }
130  // *WARNING*: At this point, dereferencing this could be a memory violation!
131 
132  lk.run_wml_action("command", vcfg, event_info);
133 }
134 
136 {
137  const std::string my_names = !gd ? cfg_["name"].str() :
139  std::string::const_iterator itor,
140  it_begin = my_names.begin(),
141  it_end = my_names.end(),
142  match_it = name.begin(),
143  match_begin = name.begin(),
144  match_end = name.end();
145  int skip_count = 0;
146  for(itor = it_begin; itor != it_end; ++itor) {
147  bool do_eat = false,
148  do_skip = false;
149  switch(*itor) {
150  case ',':
151  if(itor - it_begin - skip_count == match_it - match_begin && match_it == match_end) {
152  return true;
153  }
154  it_begin = itor + 1;
155  match_it = match_begin;
156  skip_count = 0;
157  continue;
158  case '\f':
159  case '\n':
160  case '\r':
161  case '\t':
162  case '\v':
163  do_skip = (match_it == match_begin || match_it == match_end);
164  break;
165  case ' ':
166  do_skip = (match_it == match_begin || match_it == match_end);
167  // fall through to case '_'
168  case '_':
169  do_eat = (match_it != match_end && (*match_it == ' ' || *match_it == '_'));
170  break;
171  default:
172  do_eat = (match_it != match_end && *match_it == *itor);
173  break;
174  }
175  if(do_eat) {
176  ++match_it;
177  } else if(do_skip) {
178  ++skip_count;
179  } else {
180  itor = std::find(itor, it_end, ',');
181  if(itor == it_end) {
182  return false;
183  }
184  it_begin = itor + 1;
185  match_it = match_begin;
186  skip_count = 0;
187  }
188  }
189  if(itor - it_begin - skip_count == match_it - match_begin && match_it == match_end) {
190  return true;
191  }
192  return false;
193 }
194 
195 } // end namespace game_events
196 
handler_ptr operator*()
Dereference.
Definition: handlers.cpp:59
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
bool run_wml_action(std::string const &, vconfig const &, game_events::queued_event const &)
Runs a command from an event handler.
boost::shared_ptr< event_handler > handler_ptr
Shared pointer to handler objects.
Definition: handlers.hpp:44
bool matches_name(const std::string &name, const game_data *data) const
Definition: handlers.cpp:135
void handle_event(const queued_event &event_info, handler_ptr &handler_p, game_lua_kernel &)
Handles the queued event, according to our WML instructions.
Definition: handlers.cpp:113
#define DBG_NG
Definition: handlers.cpp:42
static lg::log_domain log_engine("engine")
Templates and utility-routines for strings and numbers.
handler_vec::size_type index_
Definition: handlers.hpp:74
GLboolean reset
Definition: glew.h:3799
Domain specific events.
Definition: action_wml.cpp:93
void disable()
Disables *this, removing it from the game.
Definition: handlers.cpp:94
list_t::iterator iter_
The current element.
Definition: handlers.hpp:107
std::map< std::string, tfilter >::iterator itor
Definition: filter.cpp:199
static iterator erase(const iterator &pos)
GLuint index
Definition: glew.h:1782
static lg::log_domain log_event_handler("event_handler")
Define the game's event mechanism.
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:47
GLuint const GLchar * name
Definition: glew.h:1782
Define the handlers for the game's events mechanism.
bool find(E event, F functor)
Tests whether an event handler is available.
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
Standard logging facilities (interface).
boost::scoped_ptr< t_event_handlers > event_handlers_
Definition: manager.hpp:99
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503
event_handler(const config &cfg, bool is_menu_item, handler_vec::size_type index, manager &)
Definition: handlers.cpp:78