The Battle for Wesnoth  1.15.1+dev
help_impl.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
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  * Note:
17  * Prior to the creation of this file, all the code associated to the help
18  * browser existed in a single file src/help.cpp, including all of the
19  * widgets, topic generators, and implementation details. This totaled
20  * ~4000 lines of code.
21  *
22  * I have split it all up now, so that the gui aspects are separated from
23  * the content, the "front facing" part which the rest of the code base
24  * interacts with is in src/help/help.?pp, and the topic generators are
25  * separated. The remaining "guts" are here. It is implemented in a static
26  * singleton pattern, using "extern"'d variables, simply for ease of translation
27  * from the previous state. It would probably be a good idea to rewrite this
28  * guy as a proper C++ object. Feel free to do so, or to adopt some other
29  * design pattern.
30  */
31 
32 #pragma once
33 
34 #include "exceptions.hpp" // for error
35 #include "font/sdl_ttf.hpp" // for line_width, relative_size
36 #include "gettext.hpp"
37 #include <cstring>
38 #include <list> // for list
39 #include <memory>
40 #include <ostream> // for operator<<, stringstream, etc
41 #include <string> // for string, allocator, etc
42 #include <utility> // for pair, make_pair
43 #include <vector> // for vector, etc
44 #include <SDL2/SDL.h> // for SDL_Surface
45 #include <boost/logic/tribool.hpp>
46 #include <boost/optional.hpp>
47 
48 class config;
49 class unit_type;
51 typedef std::shared_ptr<terrain_type_data> ter_data_cache;
52 namespace help {
53 
54 /// Generate the help contents from the configurations given to the
55 /// manager.
56 void generate_contents();
57 
58 
59 /// Generate a topic text on the fly.
61 {
62 public:
63  topic_generator() = default;
64  virtual std::string operator()() const = 0;
65  virtual ~topic_generator() {}
66 };
67 
69  std::string text_;
70 public:
71  text_topic_generator(const std::string& t): text_(t) {}
72  virtual std::string operator()() const { return text_; }
73 };
74 
75 /// The text displayed in a topic. It is generated on the fly with the information
76 /// contained in generator_.
78 {
79  mutable std::vector< std::string > parsed_text_;
80  mutable std::shared_ptr<topic_generator> generator_;
81 public:
82  topic_text() = default;
83  ~topic_text() = default;
84 
85  topic_text(const std::string& t):
86  parsed_text_(),
87  generator_(std::make_shared<text_topic_generator>(t))
88  {
89  }
90 
91  explicit topic_text(std::shared_ptr<topic_generator> g):
92  parsed_text_(),
93  generator_(g)
94  {
95  }
96 
97  topic_text(const topic_text& t) = default;
98  topic_text(topic_text&& t) = default;
99  topic_text& operator=(topic_text&& t) = default;
100  topic_text& operator=(const topic_text& t) = default;
101  topic_text& operator=(std::shared_ptr<topic_generator> g);
102 
103  const std::vector<std::string>& parsed_text() const;
104 };
105 
106 /// A topic contains a title, an id and some text.
107 struct topic
108 {
109  topic() :
110  title(),
111  id(),
112  text()
113  {
114  }
115 
116  topic(const std::string &_title, const std::string &_id) :
117  title(_title),
118  id(_id),
119  text()
120  {
121  }
122 
123  topic(const std::string &_title, const std::string &_id, const std::string &_text)
124  : title(_title), id(_id), text(_text) {}
125  topic(const std::string &_title, const std::string &_id, std::shared_ptr<topic_generator> g)
126  : title(_title), id(_id), text(g) {}
127  /// Two topics are equal if their IDs are equal.
128  bool operator==(const topic &) const;
129  bool operator!=(const topic &t) const { return !operator==(t); }
130  /// Comparison on the ID.
131  bool operator<(const topic &) const;
132  std::string title, id;
133  mutable topic_text text;
134 };
135 
136 struct section;
137 typedef std::list<section> section_list;
138 typedef std::list<topic> topic_list;
139 
140 /// A section contains topics and sections along with title and ID.
141 struct section {
143  title(""),
144  id(""),
145  topics(),
146  sections(),
147  level()
148  {
149  }
150 
151  /// Two sections are equal if their IDs are equal.
152  bool operator==(const section &) const;
153  /// Comparison on the ID.
154  bool operator<(const section &) const;
155 
156  /// Allocate memory for and add the section.
157  void add_section(const section &s);
158 
159  void clear();
160  std::string title, id;
161  topic_list topics;
162  section_list sections;
163  int level;
164 };
165 
166 
167 /// To be used as a function object to locate sections and topics
168 /// with a specified ID.
169 class has_id
170 {
171 public:
172  has_id(const std::string &id) : id_(id) {}
173  bool operator()(const topic &t) { return t.id == id_; }
174  bool operator()(const section &s) { return s.id == id_; }
175  bool operator()(const section *s) { return s != nullptr && s->id == id_; }
176 private:
177  const std::string id_;
178 };
179 
180 /// To be used as a function object when sorting topic lists on the title.
182 {
183 public:
184  bool operator()(const topic &t1, const topic &t2) {
185  return translation::compare(t1.title, t2.title) < 0; }
186 };
187 
188 /// To be used as a function object when sorting section lists on the title.
190 {
191 public:
192  bool operator()(const section& s1, const section& s2) {
193  return translation::compare(s1.title, s2.title) < 0; }
194 };
195 
197 {
198 public:
199  bool operator() (const std::string &s1, const std::string &s2) const {
200  return translation::compare(s1, s2) < 0;
201  }
202 };
203 
204 /// Thrown when the help system fails to parse something.
205 struct parse_error : public game::error
206 {
207  parse_error(const std::string& msg) : game::error(msg) {}
208 };
209 
210 // Generator stuff below. Maybe move to a separate file? This one is
211 // getting crowded. Dunno if much more is needed though so I'll wait and
212 // see.
213 
214 /// Dispatch generators to their appropriate functions.
215 void generate_sections(const config *help_cfg, const std::string &generator, section &sec, int level);
216 std::vector<topic> generate_topics(const bool sort_topics,const std::string &generator);
217 std::string generate_topic_text(const std::string &generator, const config *help_cfg,
218 const section &sec, const std::vector<topic>& generated_topics);
219 std::string generate_contents_links(const std::string& section_name, config const *help_cfg);
220 std::string generate_contents_links(const section &sec, const std::vector<topic>& topics);
221 
222 /// return a hyperlink with the unit's name and pointing to the unit page
223 /// return empty string if this unit is hidden. If not yet discovered add the (?) suffix
224 std::string make_unit_link(const std::string& type_id);
225 /// return a list of hyperlinks to unit's pages (ordered or not)
226 std::vector<std::string> make_unit_links_list(
227  const std::vector<std::string>& type_id_list, bool ordered = false);
228 
229 void generate_races_sections(const config *help_cfg, section &sec, int level);
230 void generate_terrain_sections(const config* help_cfg, section &sec, int level);
231 std::vector<topic> generate_unit_topics(const bool, const std::string& race);
232 void generate_unit_sections(const config *help_cfg, section &sec, int level, const bool, const std::string& race);
234 /// Return the type of description that should be shown for a unit of
235 /// the given kind. This method is intended to filter out information
236 /// about units that should not be shown, for example due to not being
237 /// encountered.
239 std::vector<topic> generate_ability_topics(const bool);
240 std::vector<topic> generate_time_of_day_topics(const bool);
241 std::vector<topic> generate_weapon_special_topics(const bool);
242 
243 void generate_era_sections(const config *help_cfg, section &sec, int level);
244 std::vector<topic> generate_faction_topics(const config &, const bool);
245 std::vector<topic> generate_era_topics(const bool, const std::string & era_id);
246 std::vector<topic> generate_trait_topics(const bool);
247 
248 /// Parse a help config, return the top level section. Return an empty
249 /// section if cfg is nullptr.
250 section parse_config(const config *cfg);
251 /// Recursive function used by parse_config.
252 void parse_config_internal(const config *help_cfg, const config *section_cfg,
253  section &sec, int level=0);
254 
255 /// Return true if the section with id section_id is referenced from
256 /// another section in the config, or the toplevel.
257 bool section_is_referenced(const std::string &section_id, const config &cfg);
258 /// Return true if the topic with id topic_id is referenced from
259 /// another section in the config, or the toplevel.
260 bool topic_is_referenced(const std::string &topic_id, const config &cfg);
261 
262 /// Search for the topic with the specified identifier in the section
263 /// and its subsections. Return the found topic, or nullptr if none could
264 /// be found.
265 const topic *find_topic(const section &sec, const std::string &id);
266 
267 /// Search for the section with the specified identifier in the section
268 /// and its subsections. Return the found section or nullptr if none could
269 /// be found.
270 const section *find_section(const section &sec, const std::string &id);
271 
272 /// Parse a text string. Return a vector with the different parts of the
273 /// text. Each markup item is a separate part while the text between
274 /// markups are separate parts.
275 std::vector<std::string> parse_text(const std::string &text);
276 
277 /// Convert the contents to wml attributes, surrounded within
278 /// [element_name]...[/element_name]. Return the resulting WML.
279 std::string convert_to_wml(const std::string &element_name, const std::string &contents);
280 
281 /// Return the color the string represents. Return font::NORMAL_COLOR if
282 /// the string is empty or can't be matched against any other color.
283 color_t string_to_color(const std::string &s);
284 
285 /// Make a best effort to word wrap s. All parts are less than width.
286 std::vector<std::string> split_in_width(const std::string &s, const int font_size, const unsigned width);
287 
288 std::string remove_first_space(const std::string& text);
289 
290 /// Prepend all chars with meaning inside attributes with a backslash.
291 std::string escape(const std::string &s);
292 
293 /// Return the first word in s, not removing any spaces in the start of
294 /// it.
295 std::string get_first_word(const std::string &s);
296 
297 /// Load the appropriate terrain types data to use
299 
300 extern const config *game_cfg;
301 // The default toplevel.
303 // All sections and topics not referenced from the default toplevel.
305 
306 extern int last_num_encountered_units;
308 extern boost::tribool last_debug_state;
309 
310 extern std::vector<std::string> empty_string_vector;
311 extern const int max_section_level;
312 extern const int title_size;
313 extern const int title2_size;
314 extern const int box_width;
315 extern const int normal_font_size;
316 extern const unsigned max_history;
317 extern const std::string topic_img;
318 extern const std::string closed_section_img;
319 extern const std::string open_section_img;
320 // The topic to open by default when opening the help dialog.
321 extern const std::string default_show_topic;
322 extern const std::string unknown_unit_topic;
323 extern const std::string unit_prefix;
324 extern const std::string terrain_prefix;
325 extern const std::string race_prefix;
326 extern const std::string faction_prefix;
327 extern const std::string era_prefix;
328 extern const std::string variation_prefix;
329 extern const std::string ability_prefix;
330 
331 // id starting with '.' are hidden
332 std::string hidden_symbol(bool hidden = true);
333 
334 bool is_visible_id(const std::string &id);
335 
336 /// Return true if the id is valid for user defined topics and
337 /// sections. Some IDs are special, such as toplevel and may not be
338 /// be defined in the config.
339 bool is_valid_id(const std::string &id);
340 
341  // Helpers for making generation of topics easier.
342 
343 inline std::string make_link(const std::string& text, const std::string& dst)
344  {
345  // some sorting done on list of links may rely on the fact that text is first
346  return "<ref>text='" + help::escape(text) + "' dst='" + help::escape(dst) + "'</ref>";
347  }
348 
349 inline std::string jump_to(const unsigned pos)
350  {
351  std::stringstream ss;
352  ss << "<jump>to=" << pos << "</jump>";
353  return ss.str();
354  }
355 
356 inline std::string jump(const unsigned amount)
357  {
358  std::stringstream ss;
359  ss << "<jump>amount=" << amount << "</jump>";
360  return ss.str();
361  }
362 
363 inline std::string bold(const std::string &s)
364  {
365  std::stringstream ss;
366  ss << "<bold>text='" << help::escape(s) << "'</bold>";
367  return ss.str();
368  }
369 
370 // A string to be displayed and its width.
371 typedef std::pair< std::string, unsigned > item;
372 
373 typedef std::vector<std::vector<help::item> > table_spec;
374 // Create a table using the table specs. Return markup with jumps
375 // that create a table. The table spec contains a vector with
376 // vectors with pairs. The pairs are the markup string that should
377 // be in a cell, and the width of that cell.
378 std::string generate_table(const table_spec &tab, const unsigned int spacing=font::relative_size(20));
379 
380 // Return the width for the image with filename.
381 unsigned image_width(const std::string &filename);
382 
383 // Add to the vector v an help::item for the string s, preceded by the given image if any.
384 void push_tab_pair(std::vector<help::item> &v, const std::string &s, const boost::optional<std::string> &image = {}, unsigned padding = 0);
385 
386 } // end namespace help
std::string jump_to(const unsigned pos)
Definition: help_impl.hpp:349
std::shared_ptr< terrain_type_data > ter_data_cache
Definition: help_impl.hpp:50
const std::string ability_prefix
Definition: help_impl.cpp:95
section parse_config(const config *cfg)
Parse a help config, return the top level section.
Definition: help_impl.cpp:251
std::string id
Definition: help_impl.hpp:160
std::string make_unit_link(const std::string &type_id)
return a hyperlink with the unit&#39;s name and pointing to the unit page return empty string if this uni...
Definition: help_impl.cpp:712
const std::string open_section_img
Definition: help_impl.cpp:85
std::vector< topic > generate_trait_topics(const bool sort_generated)
Definition: help_impl.cpp:650
const std::string unit_prefix
Definition: help_impl.cpp:89
std::vector< topic > generate_unit_topics(const bool sort_generated, const std::string &race)
Definition: help_impl.cpp:902
const std::string era_prefix
Definition: help_impl.cpp:93
void generate_unit_sections(const config *, section &sec, int level, const bool, const std::string &race)
Definition: help_impl.cpp:868
const std::string topic_img
Definition: help_impl.cpp:83
topic_text(const std::string &t)
Definition: help_impl.hpp:85
const int title_size
Definition: help_impl.cpp:78
bool operator()(const section &s)
Definition: help_impl.hpp:174
const std::string closed_section_img
Definition: help_impl.cpp:84
std::string remove_first_space(const std::string &text)
Definition: help_impl.cpp:1293
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:141
const std::string unknown_unit_topic
Definition: help_impl.cpp:88
const std::string race_prefix
Definition: help_impl.cpp:91
std::string generate_topic_text(const std::string &generator, const config *help_cfg, const section &sec, const std::vector< topic > &generated_topics)
Definition: help_impl.cpp:309
virtual std::string operator()() const
Definition: help_impl.hpp:72
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
topic(const std::string &_title, const std::string &_id, const std::string &_text)
Definition: help_impl.hpp:123
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
Definition: gettext.cpp:458
boost::tribool last_debug_state
Definition: help_impl.cpp:73
int relative_size(int size)
Definition: constants.hpp:29
Thrown when the help system fails to parse something.
Definition: help_impl.hpp:205
parse_error(const std::string &msg)
Definition: help_impl.hpp:207
void clear(const std::string &key)
Definition: general.cpp:205
topic_text(std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:91
std::vector< std::string > empty_string_vector
Definition: help_impl.cpp:76
text_topic_generator(const std::string &t)
Definition: help_impl.hpp:71
const std::string id_
Definition: help_impl.hpp:177
STL namespace.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
const int normal_font_size
Definition: help_impl.cpp:81
unsigned image_width(const std::string &filename)
Definition: help_impl.cpp:1423
const std::string terrain_prefix
Definition: help_impl.cpp:90
int last_num_encountered_terrains
Definition: help_impl.cpp:72
std::list< section > section_list
Definition: help_impl.hpp:136
const config * game_cfg
Definition: help_impl.cpp:65
color_t string_to_color(const std::string &cmp_str)
Return the color the string represents.
Definition: help_impl.cpp:1250
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1395
std::vector< topic > generate_weapon_special_topics(const bool sort_generated)
Definition: help_impl.cpp:375
std::vector< std::string > make_unit_links_list(const std::vector< std::string > &type_id_list, bool ordered)
return a list of hyperlinks to unit&#39;s pages (ordered or not)
Definition: help_impl.cpp:738
std::string bold(const std::string &s)
Definition: help_impl.hpp:363
A single unit type that the player may recruit.
Definition: types.hpp:42
void generate_sections(const config *help_cfg, const std::string &generator, section &sec, int level)
Dispatch generators to their appropriate functions.
Definition: help_impl.cpp:290
help::section hidden_sections
Definition: help_impl.cpp:69
section_list sections
Definition: help_impl.hpp:162
const section * find_section(const section &sec, const std::string &id)
Search for the section with the specified identifier in the section and its subsections.
Definition: help_impl.cpp:1110
std::string id
Definition: help_impl.hpp:132
To be used as a function object to locate sections and topics with a specified ID.
Definition: help_impl.hpp:169
The text displayed in a topic.
Definition: help_impl.hpp:77
std::string generate_table(const table_spec &tab, const unsigned int spacing)
Definition: help_impl.cpp:1447
void push_tab_pair(std::vector< help::item > &v, const std::string &s, const boost::optional< std::string > &image, unsigned padding)
Definition: help_impl.cpp:1433
std::vector< std::vector< help::item > > table_spec
Definition: help_impl.hpp:373
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1391
bool operator()(const topic &t1, const topic &t2)
Definition: help_impl.hpp:184
std::string title
Definition: help_impl.hpp:160
std::vector< topic > generate_era_topics(const bool sort_generated, const std::string &era_id)
Definition: help_impl.cpp:538
UNIT_DESCRIPTION_TYPE
Definition: help_impl.hpp:233
void generate_terrain_sections(const config *, section &sec, int)
Definition: help_impl.cpp:816
std::vector< topic > generate_faction_topics(const config &era, const bool sort_generated)
Definition: help_impl.cpp:574
std::vector< std::string > parsed_text_
Definition: help_impl.hpp:79
ter_data_cache load_terrain_types_data()
Load the appropriate terrain types data to use.
Definition: help_impl.cpp:1496
std::list< topic > topic_list
Definition: help_impl.hpp:138
std::shared_ptr< topic_generator > generator_
Definition: help_impl.hpp:80
void parse_config_internal(const config *help_cfg, const config *section_cfg, section &sec, int level)
Recursive function used by parse_config.
Definition: help_impl.cpp:145
bool operator!=(const topic &t) const
Definition: help_impl.hpp:129
const int box_width
Definition: help_impl.cpp:80
bool section_is_referenced(const std::string &section_id, const config &cfg)
Return true if the section with id section_id is referenced from another section in the config...
Definition: help_impl.cpp:97
bool topic_is_referenced(const std::string &topic_id, const config &cfg)
Return true if the topic with id topic_id is referenced from another section in the config...
Definition: help_impl.cpp:121
To be used as a function object when sorting section lists on the title.
Definition: help_impl.hpp:189
const std::string variation_prefix
Definition: help_impl.cpp:94
int last_num_encountered_units
Definition: help_impl.cpp:71
bool operator()(const section *s)
Definition: help_impl.hpp:175
std::string make_link(const std::string &text, const std::string &dst)
Definition: help_impl.hpp:343
bool operator==(const config &a, const config &b)
Definition: config.cpp:1405
std::string convert_to_wml(const std::string &element_name, const std::string &contents)
Convert the contents to wml attributes, surrounded within [element_name]...[/element_name].
Definition: help_impl.cpp:1199
static map_location::DIRECTION s
double g
Definition: astarsearch.cpp:64
static bool operator<(const placing_info &a, const placing_info &b)
Definition: game_state.cpp:138
void generate_races_sections(const config *help_cfg, section &sec, int level)
Definition: help_impl.cpp:753
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60
std::string escape(const std::string &s)
Prepend all chars with meaning inside attributes with a backslash.
Definition: help_impl.cpp:1490
std::vector< std::string > parse_text(const std::string &text)
Parse a text string.
Definition: help_impl.cpp:1126
const unsigned max_history
Definition: help_impl.cpp:82
std::vector< topic > generate_time_of_day_topics(const bool)
Definition: help_impl.cpp:343
std::string generate_contents_links(const std::string &section_name, config const *help_cfg)
Definition: help_impl.cpp:1003
const std::string faction_prefix
Definition: help_impl.cpp:92
std::string jump(const unsigned amount)
Definition: help_impl.hpp:356
has_id(const std::string &id)
Definition: help_impl.hpp:172
const std::string default_show_topic
Definition: help_impl.cpp:87
double t
Definition: astarsearch.cpp:64
void generate_contents()
Generate the help contents from the configurations given to the manager.
Definition: help_impl.cpp:1327
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
std::vector< topic > generate_topics(const bool sort_generated, const std::string &generator)
Definition: help_impl.cpp:261
virtual std::string operator()() const =0
const topic * find_topic(const section &sec, const std::string &id)
Search for the topic with the specified identifier in the section and its subsections.
Definition: help_impl.cpp:1094
topic(const std::string &_title, const std::string &_id, std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:125
this module manages the cache of images.
Generate a topic text on the fly.
Definition: help_impl.hpp:60
bool operator()(const topic &t)
Definition: help_impl.hpp:173
const int title2_size
Definition: help_impl.cpp:79
A topic contains a title, an id and some text.
Definition: help_impl.hpp:107
Definition: help.cpp:56
virtual ~topic_generator()
Definition: help_impl.hpp:65
std::string title
Definition: help_impl.hpp:132
topic(const std::string &_title, const std::string &_id)
Definition: help_impl.hpp:116
bool is_valid_id(const std::string &id)
Return true if the id is valid for user defined topics and sections.
Definition: help_impl.cpp:1402
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
std::string get_first_word(const std::string &s)
Return the first word in s, not removing any spaces in the start of it.
Definition: help_impl.cpp:1301
const int font_size
Definition: button.cpp:40
UNIT_DESCRIPTION_TYPE description_type(const unit_type &type)
Return the type of description that should be shown for a unit of the given kind. ...
Definition: help_impl.cpp:989
std::vector< topic > generate_ability_topics(const bool sort_generated)
Definition: help_impl.cpp:472
void generate_era_sections(const config *help_cfg, section &sec, int level)
Definition: help_impl.cpp:793
const int max_section_level
Definition: help_impl.cpp:77
bool operator()(const section &s1, const section &s2)
Definition: help_impl.hpp:192
To be used as a function object when sorting topic lists on the title.
Definition: help_impl.hpp:181
std::vector< std::string > split_in_width(const std::string &s, const int font_size, const unsigned width)
Make a best effort to word wrap s. All parts are less than width.
Definition: help_impl.cpp:1274
topic_list topics
Definition: help_impl.hpp:161
topic_text text
Definition: help_impl.hpp:133
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:371
std::shared_ptr< terrain_type_data > ter_data_cache
help::section default_toplevel
Definition: help_impl.cpp:67