The Battle for Wesnoth  1.15.7+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 https://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 game_config_view;
49 class config;
50 class unit_type;
52 typedef std::shared_ptr<terrain_type_data> ter_data_cache;
53 namespace help {
54 
55 /// Generate the help contents from the configurations given to the
56 /// manager.
57 void generate_contents();
58 
59 
60 /// Generate a topic text on the fly.
62 {
63 public:
64  topic_generator() = default;
65  virtual std::string operator()() const = 0;
66  virtual ~topic_generator() {}
67 };
68 
71 public:
72  text_topic_generator(const std::string& t): text_(t) {}
73  virtual std::string operator()() const { return text_; }
74 };
75 
76 /// The text displayed in a topic. It is generated on the fly with the information
77 /// contained in generator_.
79 {
80  mutable std::vector< std::string > parsed_text_;
81  mutable std::shared_ptr<topic_generator> generator_;
82 public:
83  topic_text() = default;
84  ~topic_text() = default;
85 
87  parsed_text_(),
88  generator_(std::make_shared<text_topic_generator>(t))
89  {
90  }
91 
92  explicit topic_text(std::shared_ptr<topic_generator> g):
93  parsed_text_(),
94  generator_(g)
95  {
96  }
97 
98  topic_text(const topic_text& t) = default;
99  topic_text(topic_text&& t) = default;
100  topic_text& operator=(topic_text&& t) = default;
101  topic_text& operator=(const topic_text& t) = default;
102  topic_text& operator=(std::shared_ptr<topic_generator> g);
103 
104  const std::vector<std::string>& parsed_text() const;
105 };
106 
107 /// A topic contains a title, an id and some text.
108 struct topic
109 {
110  topic() :
111  title(),
112  id(),
113  text()
114  {
115  }
116 
117  topic(const std::string &_title, const std::string &_id) :
118  title(_title),
119  id(_id),
120  text()
121  {
122  }
123 
124  topic(const std::string &_title, const std::string &_id, const std::string &_text)
125  : title(_title), id(_id), text(_text) {}
126  topic(const std::string &_title, const std::string &_id, std::shared_ptr<topic_generator> g)
127  : title(_title), id(_id), text(g) {}
128  /// Two topics are equal if their IDs are equal.
129  bool operator==(const topic &) const;
130  bool operator!=(const topic &t) const { return !operator==(t); }
131  /// Comparison on the ID.
132  bool operator<(const topic &) const;
134  mutable topic_text text;
135 };
136 
137 struct section;
138 typedef std::list<section> section_list;
139 typedef std::list<topic> topic_list;
140 
141 /// A section contains topics and sections along with title and ID.
142 struct section {
144  title(""),
145  id(""),
146  topics(),
147  sections()
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();
161  topic_list topics;
162  section_list sections;
163 };
164 
165 
166 /// To be used as a function object to locate sections and topics
167 /// with a specified ID.
168 class has_id
169 {
170 public:
171  has_id(const std::string &id) : id_(id) {}
172  bool operator()(const topic &t) { return t.id == id_; }
173  bool operator()(const section &s) { return s.id == id_; }
174  bool operator()(const section *s) { return s != nullptr && s->id == id_; }
175 private:
177 };
178 
179 /// To be used as a function object when sorting topic lists on the title.
181 {
182 public:
183  bool operator()(const topic &t1, const topic &t2) {
184  return translation::compare(t1.title, t2.title) < 0; }
185 };
186 
187 /// To be used as a function object when sorting section lists on the title.
189 {
190 public:
191  bool operator()(const section& s1, const section& s2) {
192  return translation::compare(s1.title, s2.title) < 0; }
193 };
194 
196 {
197 public:
198  bool operator() (const std::string &s1, const std::string &s2) const {
199  return translation::compare(s1, s2) < 0;
200  }
201 };
202 
203 /// Thrown when the help system fails to parse something.
204 struct parse_error : public game::error
205 {
206  parse_error(const std::string& msg) : game::error(msg) {}
207 };
208 
209 // Generator stuff below. Maybe move to a separate file? This one is
210 // getting crowded. Dunno if much more is needed though so I'll wait and
211 // see.
212 
213 /// Dispatch generators to their appropriate functions.
214 void generate_sections(const config *help_cfg, const std::string &generator, section &sec, int level);
215 std::vector<topic> generate_topics(const bool sort_topics,const std::string &generator);
216 std::string generate_topic_text(const std::string &generator, const config *help_cfg,
217 const section &sec, const std::vector<topic>& generated_topics);
218 std::string generate_contents_links(const std::string& section_name, const config *help_cfg);
219 std::string generate_contents_links(const section &sec, const std::vector<topic>& topics);
220 
221 /// return a hyperlink with the unit's name and pointing to the unit page
222 /// return empty string if this unit is hidden. If not yet discovered add the (?) suffix
223 std::string make_unit_link(const std::string& type_id);
224 /// return a list of hyperlinks to unit's pages (ordered or not)
225 std::vector<std::string> make_unit_links_list(
226  const std::vector<std::string>& type_id_list, bool ordered = false);
227 
228 void generate_races_sections(const config *help_cfg, section &sec, int level);
229 void generate_terrain_sections(section &sec, int level);
230 std::vector<topic> generate_unit_topics(const bool, const std::string& race);
231 void generate_unit_sections(const config *help_cfg, section &sec, int level, const bool, const std::string& race);
234  /** Ignore this unit for documentation purposes. */
236  /**
237  * Although the unit itself is hidden, traits reachable via this unit are not hidden.
238  *
239  * This is a bug workaround - traits are defined by WML macros, and therefore the help
240  * system has to use a place where that macro is instanciated to provide the documentation.
241  * None of the normal unit types has the "loyal" trait, but there is a hidden unit which
242  * does, purely to support the help system.
243  */
245 };
246 /// Return the type of description that should be shown for a unit of
247 /// the given kind. This method is intended to filter out information
248 /// about units that should not be shown, for example due to not being
249 /// encountered.
251 std::vector<topic> generate_ability_topics(const bool);
252 std::vector<topic> generate_time_of_day_topics(const bool);
253 std::vector<topic> generate_weapon_special_topics(const bool);
254 
255 void generate_era_sections(const config *help_cfg, section &sec, int level);
256 std::vector<topic> generate_faction_topics(const config &, const bool);
257 std::vector<topic> generate_era_topics(const bool, const std::string & era_id);
258 std::vector<topic> generate_trait_topics(const bool);
259 
260 /// Parse a help config, return the top level section. Return an empty
261 /// section if cfg is nullptr.
262 section parse_config(const config *cfg);
263 /// Recursive function used by parse_config.
264 void parse_config_internal(const config *help_cfg, const config *section_cfg,
265  section &sec, int level=0);
266 
267 /// Return true if the section with id section_id is referenced from
268 /// another section in the config, or the toplevel.
269 bool section_is_referenced(const std::string &section_id, const config &cfg);
270 /// Return true if the topic with id topic_id is referenced from
271 /// another section in the config, or the toplevel.
272 bool topic_is_referenced(const std::string &topic_id, const config &cfg);
273 
274 /// Search for the topic with the specified identifier in the section
275 /// and its subsections. Return the found topic, or nullptr if none could
276 /// be found.
277 const topic *find_topic(const section &sec, const std::string &id);
278 
279 /// Search for the section with the specified identifier in the section
280 /// and its subsections. Return the found section or nullptr if none could
281 /// be found.
282 const section *find_section(const section &sec, const std::string &id);
283 section *find_section(section &sec, const std::string &id);
284 
285 /// Parse a text string. Return a vector with the different parts of the
286 /// text. Each markup item is a separate part while the text between
287 /// markups are separate parts.
288 std::vector<std::string> parse_text(const std::string &text);
289 
290 /// Convert the contents to wml attributes, surrounded within
291 /// [element_name]...[/element_name]. Return the resulting WML.
292 std::string convert_to_wml(const std::string &element_name, const std::string &contents);
293 
294 /// Return the color the string represents. Return font::NORMAL_COLOR if
295 /// the string is empty or can't be matched against any other color.
297 
298 /// Make a best effort to word wrap s. All parts are less than width.
299 std::vector<std::string> split_in_width(const std::string &s, const int font_size, const unsigned width);
300 
302 
303 /// Prepend all chars with meaning inside attributes with a backslash.
305 
306 /// Return the first word in s, not removing any spaces in the start of
307 /// it.
309 
310 /// Load the appropriate terrain types data to use
312 
313 extern const game_config_view *game_cfg;
314 // The default toplevel.
316 // All sections and topics not referenced from the default toplevel.
318 
319 extern int last_num_encountered_units;
321 extern boost::tribool last_debug_state;
322 
323 extern std::vector<std::string> empty_string_vector;
324 extern const int max_section_level;
325 extern const int title_size;
326 extern const int title2_size;
327 extern const int box_width;
328 extern const int normal_font_size;
329 extern const unsigned max_history;
330 extern const std::string topic_img;
331 extern const std::string closed_section_img;
332 extern const std::string open_section_img;
333 // The topic to open by default when opening the help dialog.
334 extern const std::string default_show_topic;
335 extern const std::string unknown_unit_topic;
336 extern const std::string unit_prefix;
337 extern const std::string terrain_prefix;
338 extern const std::string race_prefix;
339 extern const std::string faction_prefix;
340 extern const std::string era_prefix;
341 extern const std::string variation_prefix;
342 extern const std::string ability_prefix;
343 
344 // id starting with '.' are hidden
345 std::string hidden_symbol(bool hidden = true);
346 
347 bool is_visible_id(const std::string &id);
348 
349 /// Return true if the id is valid for user defined topics and
350 /// sections. Some IDs are special, such as toplevel and may not be
351 /// be defined in the config.
352 bool is_valid_id(const std::string &id);
353 
354  // Helpers for making generation of topics easier.
355 
356 inline std::string make_link(const std::string& text, const std::string& dst)
357  {
358  // some sorting done on list of links may rely on the fact that text is first
359  return "<ref>text='" + help::escape(text) + "' dst='" + help::escape(dst) + "'</ref>";
360  }
361 
362 inline std::string jump_to(const unsigned pos)
363  {
364  std::stringstream ss;
365  ss << "<jump>to=" << pos << "</jump>";
366  return ss.str();
367  }
368 
369 inline std::string jump(const unsigned amount)
370  {
371  std::stringstream ss;
372  ss << "<jump>amount=" << amount << "</jump>";
373  return ss.str();
374  }
375 
377  {
378  std::stringstream ss;
379  ss << "<bold>text='" << help::escape(s) << "'</bold>";
380  return ss.str();
381  }
382 
383 // A string to be displayed and its width.
384 typedef std::pair< std::string, unsigned > item;
385 
386 typedef std::vector<std::vector<help::item> > table_spec;
387 // Create a table using the table specs. Return markup with jumps
388 // that create a table. The table spec contains a vector with
389 // vectors with pairs. The pairs are the markup string that should
390 // be in a cell, and the width of that cell.
391 std::string generate_table(const table_spec &tab, const unsigned int spacing=font::relative_size(20));
392 
393 // Return the width for the image with filename.
394 unsigned image_width(const std::string &filename);
395 
396 // Add to the vector v an help::item for the string s, preceded by the given image if any.
397 void push_tab_pair(std::vector<help::item> &v, const std::string &s, const boost::optional<std::string> &image = {}, unsigned padding = 0);
398 
399 } // end namespace help
std::string jump_to(const unsigned pos)
Definition: help_impl.hpp:362
std::shared_ptr< terrain_type_data > ter_data_cache
Definition: help_impl.hpp:51
const std::string ability_prefix
Definition: help_impl.cpp:96
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
Ignore this unit for documentation purposes.
Definition: help_impl.hpp:235
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:733
const std::string open_section_img
Definition: help_impl.cpp:86
std::vector< topic > generate_trait_topics(const bool sort_generated)
Definition: help_impl.cpp:670
const std::string unit_prefix
Definition: help_impl.cpp:90
std::vector< topic > generate_unit_topics(const bool sort_generated, const std::string &race)
Definition: help_impl.cpp:922
const std::string era_prefix
Definition: help_impl.cpp:94
const std::string topic_img
Definition: help_impl.cpp:84
topic_text(const std::string &t)
Definition: help_impl.hpp:86
const int title_size
Definition: help_impl.cpp:79
bool operator()(const section &s)
Definition: help_impl.hpp:173
const std::string closed_section_img
Definition: help_impl.cpp:85
std::string remove_first_space(const std::string &text)
Definition: help_impl.cpp:1366
A section contains topics and sections along with title and ID.
Definition: help_impl.hpp:142
const std::string unknown_unit_topic
Definition: help_impl.cpp:89
const std::string race_prefix
Definition: help_impl.cpp:92
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:73
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:124
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
Definition: gettext.cpp:457
boost::tribool last_debug_state
Definition: help_impl.cpp:75
int relative_size(int size)
Definition: constants.hpp:29
Thrown when the help system fails to parse something.
Definition: help_impl.hpp:204
parse_error(const std::string &msg)
Definition: help_impl.hpp:206
void clear(const std::string &key)
Definition: general.cpp:204
topic_text(std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:92
std::vector< std::string > empty_string_vector
Definition: help_impl.cpp:77
Although the unit itself is hidden, traits reachable via this unit are not hidden.
Definition: help_impl.hpp:244
text_topic_generator(const std::string &t)
Definition: help_impl.hpp:72
const std::string id_
Definition: help_impl.hpp:176
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:82
unsigned image_width(const std::string &filename)
Definition: help_impl.cpp:1493
const std::string terrain_prefix
Definition: help_impl.cpp:91
int last_num_encountered_terrains
Definition: help_impl.cpp:74
std::list< section > section_list
Definition: help_impl.hpp:137
color_t string_to_color(const std::string &cmp_str)
Return the color the string represents.
Definition: help_impl.cpp:1323
bool is_visible_id(const std::string &id)
Definition: help_impl.cpp:1465
std::vector< topic > generate_weapon_special_topics(const bool sort_generated)
Definition: help_impl.cpp:396
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:759
std::string bold(const std::string &s)
Definition: help_impl.hpp:376
A single unit type that the player may recruit.
Definition: types.hpp:44
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:71
section_list sections
Definition: help_impl.hpp:162
Contains the database of all known terrain types, both those defined explicitly by WML [terrain_type]...
Definition: type_data.hpp:39
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:1178
std::string id
Definition: help_impl.hpp:133
To be used as a function object to locate sections and topics with a specified ID.
Definition: help_impl.hpp:168
The text displayed in a topic.
Definition: help_impl.hpp:78
std::string generate_table(const table_spec &tab, const unsigned int spacing)
Definition: help_impl.cpp:1517
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:1503
std::vector< std::vector< help::item > > table_spec
Definition: help_impl.hpp:386
std::string hidden_symbol(bool hidden)
Definition: help_impl.cpp:1461
bool operator()(const topic &t1, const topic &t2)
Definition: help_impl.hpp:183
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:559
UNIT_DESCRIPTION_TYPE
Definition: help_impl.hpp:232
std::vector< topic > generate_faction_topics(const config &era, const bool sort_generated)
Definition: help_impl.cpp:595
std::vector< std::string > parsed_text_
Definition: help_impl.hpp:80
ter_data_cache load_terrain_types_data()
Load the appropriate terrain types data to use.
Definition: help_impl.cpp:1566
std::list< topic > topic_list
Definition: help_impl.hpp:139
std::shared_ptr< topic_generator > generator_
Definition: help_impl.hpp:81
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:146
bool operator!=(const topic &t) const
Definition: help_impl.hpp:130
const int box_width
Definition: help_impl.cpp:81
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:98
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:122
void generate_unit_sections(const config *, section &sec, int, const bool, const std::string &race)
Definition: help_impl.cpp:889
To be used as a function object when sorting section lists on the title.
Definition: help_impl.hpp:188
const std::string variation_prefix
Definition: help_impl.cpp:95
void generate_terrain_sections(section &sec, int)
Definition: help_impl.cpp:837
int last_num_encountered_units
Definition: help_impl.cpp:73
bool operator()(const section *s)
Definition: help_impl.hpp:174
std::string make_link(const std::string &text, const std::string &dst)
Definition: help_impl.hpp:356
bool operator==(const config &a, const config &b)
Definition: config.cpp:1418
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:1272
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:140
const game_config_view * game_cfg
Definition: help_impl.cpp:67
void generate_races_sections(const config *help_cfg, section &sec, int level)
Definition: help_impl.cpp:774
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:1560
std::vector< std::string > parse_text(const std::string &text)
Parse a text string.
Definition: help_impl.cpp:1199
const unsigned max_history
Definition: help_impl.cpp:83
std::vector< topic > generate_time_of_day_topics(const bool)
Definition: help_impl.cpp:349
std::string generate_contents_links(const std::string &section_name, config const *help_cfg)
Definition: help_impl.cpp:1073
const std::string faction_prefix
Definition: help_impl.cpp:93
std::string jump(const unsigned amount)
Definition: help_impl.hpp:369
has_id(const std::string &id)
Definition: help_impl.hpp:171
const std::string default_show_topic
Definition: help_impl.cpp:88
double t
Definition: astarsearch.cpp:64
void generate_contents()
Generate the help contents from the configurations given to the manager.
Definition: help_impl.cpp:1400
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:1162
topic(const std::string &_title, const std::string &_id, std::shared_ptr< topic_generator > g)
Definition: help_impl.hpp:126
this module manages the cache of images.
Generate a topic text on the fly.
Definition: help_impl.hpp:61
bool operator()(const topic &t)
Definition: help_impl.hpp:172
const int title2_size
Definition: help_impl.cpp:80
A topic contains a title, an id and some text.
Definition: help_impl.hpp:108
Definition: help.cpp:55
virtual ~topic_generator()
Definition: help_impl.hpp:66
std::string title
Definition: help_impl.hpp:133
topic(const std::string &_title, const std::string &_id)
Definition: help_impl.hpp:117
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:1472
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
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:1374
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:1053
std::vector< topic > generate_ability_topics(const bool sort_generated)
Definition: help_impl.cpp:493
void generate_era_sections(const config *help_cfg, section &sec, int level)
Definition: help_impl.cpp:814
const int max_section_level
Definition: help_impl.cpp:78
bool operator()(const section &s1, const section &s2)
Definition: help_impl.hpp:191
To be used as a function object when sorting topic lists on the title.
Definition: help_impl.hpp:180
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:1347
topic_list topics
Definition: help_impl.hpp:161
topic_text text
Definition: help_impl.hpp:134
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:384
auto * ss
Definition: result_set.cpp:281
std::shared_ptr< terrain_type_data > ter_data_cache
help::section default_toplevel
Definition: help_impl.cpp:69