The Battle for Wesnoth  1.17.0-dev
build_info.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2015 - 2021
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
18 #include "build_info.hpp"
19 
20 #include "desktop/version.hpp"
21 #include "game_config.hpp"
22 #include "filesystem.hpp"
23 #include "formatter.hpp"
24 #include "gettext.hpp"
27 #include "game_version.hpp"
28 #include "sound.hpp"
29 #include "video.hpp"
30 #include "addon/manager.hpp"
31 
32 #include <algorithm>
33 #include <fstream>
34 #include <iomanip>
35 
36 #include "lua/lua.h"
37 
38 #include <SDL2/SDL.h>
39 #include <SDL2/SDL_image.h>
40 #include <SDL2/SDL_mixer.h>
41 
42 #include <boost/algorithm/string.hpp>
43 #include <boost/predef.h>
44 #include <boost/version.hpp>
45 
46 #ifndef __APPLE__
47 #include <openssl/crypto.h>
48 #include <openssl/opensslv.h>
49 #endif
50 
51 #include <pango/pangocairo.h>
52 
53 #ifdef __APPLE__
54 // apple_notification.mm uses Foundation.h, which is an Objective-C header;
55 // but CoreFoundation.h is a C header which also defines these.
56 #include <CoreFoundation/CoreFoundation.h>
57 #endif
58 
59 namespace game_config
60 {
61 
62 namespace {
63 
64 struct version_table_manager
65 {
66  std::vector<std::string> compiled, linked, names;
67  std::vector<optional_feature> features;
68 
69  version_table_manager();
70 };
71 
72 const version_table_manager versions;
73 
74 #if 0
75 std::string format_version(unsigned a, unsigned b, unsigned c)
76 {
77  return formatter() << a << '.' << b << '.' << c;
78 }
79 #endif
80 
81 std::string format_version(const SDL_version& v)
82 {
83  return formatter() << static_cast<unsigned>(v.major) << '.'
84  << static_cast<unsigned>(v.minor) << '.'
85  << static_cast<unsigned>(v.patch);
86 }
87 
88 #ifndef __APPLE__
89 
90 std::string format_openssl_patch_level(uint8_t p)
91 {
92  return p <= 26
93  ? std::string(1, 'a' + static_cast<char>(p) - 1)
94  : "patch" + std::to_string(p);
95 }
96 
97 std::string format_openssl_version(long v)
98 {
99  int major, minor, fix, patch, status;
100  std::ostringstream fmt;
101 
102  //
103  // The people who maintain OpenSSL are not from this world. I suppose it's
104  // only fair that I'm the one who gets to try to make sense of their version
105  // encoding scheme. -- shadowm
106  //
107 
108  if(v < 0x0930L) {
109  // Pre-0.9.3 seems simpler times overall.
110  minor = v & 0x0F00L >> 8;
111  fix = v & 0x00F0L >> 4;
112  patch = v & 0x000FL;
113 
114  fmt << "0." << minor << '.' << fix;
115  if(patch) {
116  fmt << format_openssl_patch_level(patch);
117  }
118  } else {
119  //
120  // Note that they either assume the major version will never be greater than
121  // 9, they plan to use hexadecimal digits for versions 10.x.x through
122  // 15.x.x, or they expect long to be always > 32-bits by then. Who the hell
123  // knows, really.
124  //
125  major = (v & 0xF0000000L) >> 28;
126  minor = (v & 0x0FF00000L) >> 20;
127  fix = (v & 0x000FF000L) >> 12;
128  patch = (v & 0x00000FF0L) >> 4;
129  status = (v & 0x0000000FL);
130 
131  if(v < 0x00905100L) {
132  //
133  // From wiki.openssl.org (also mentioned in opensslv.h, in the most oblique
134  // fashion possible):
135  //
136  // "Versions between 0.9.3 and 0.9.5 had a version identifier with this interpretation:
137  // MMNNFFRBB major minor fix final beta/patch"
138  //
139  // Both the wiki and opensslv.h fail to accurately list actual version
140  // numbers that ended up used in the wild -- e.g. 0.9.3a is supposedly
141  // 0x0090301f when it really was 0x00903101.
142  //
143  const uint8_t is_final = (v & 0xF00L) >> 8;
144  status = is_final ? 0xF : 0;
145  patch = v & 0xFFL;
146  } else if(v < 0x00906000L) {
147  //
148  // Quoth opensslv.h:
149  //
150  // "For continuity reasons (because 0.9.5 is already out, and is coded
151  // 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
152  // part is slightly different, by setting the highest bit. This means
153  // that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start
154  // with 0x0090600S..."
155  //
156  patch ^= 1 << 7;
157  }
158 
159  fmt << major << '.' << minor << '.' << fix;
160 
161  if(patch) {
162  fmt << format_openssl_patch_level(patch);
163  }
164 
165  if(status == 0x0) {
166  fmt << "-dev";
167  } else if(status < 0xF) {
168  fmt << "-beta" << status;
169  }
170  }
171 
172  return fmt.str();
173 
174 }
175 
176 #endif
177 
178 version_table_manager::version_table_manager()
179  : compiled(LIB_COUNT, "")
180  , linked(LIB_COUNT, "")
181  , names(LIB_COUNT, "")
182  , features()
183 {
184  SDL_version sdl_version;
185 
186 
187  //
188  // SDL
189  //
190 
191  SDL_VERSION(&sdl_version);
192  compiled[LIB_SDL] = format_version(sdl_version);
193 
194  SDL_GetVersion(&sdl_version);
195  linked[LIB_SDL] = format_version(sdl_version);
196 
197  names[LIB_SDL] = "SDL";
198 
199  //
200  // SDL_image
201  //
202 
203  SDL_IMAGE_VERSION(&sdl_version);
204  compiled[LIB_SDL_IMAGE] = format_version(sdl_version);
205 
206  const SDL_version* sdl_rt_version = IMG_Linked_Version();
207  if(sdl_rt_version) {
208  linked[LIB_SDL_IMAGE] = format_version(*sdl_rt_version);
209  }
210 
211  names[LIB_SDL_IMAGE] = "SDL_image";
212 
213  //
214  // SDL_mixer
215  //
216 
217  SDL_MIXER_VERSION(&sdl_version);
218  compiled[LIB_SDL_MIXER] = format_version(sdl_version);
219 
220  sdl_rt_version = Mix_Linked_Version();
221  if(sdl_rt_version) {
222  linked[LIB_SDL_MIXER] = format_version(*sdl_rt_version);
223  }
224 
225  names[LIB_SDL_MIXER] = "SDL_mixer";
226 
227  //
228  // Boost
229  //
230 
231  compiled[LIB_BOOST] = BOOST_LIB_VERSION;
232  std::replace(compiled[LIB_BOOST].begin(), compiled[LIB_BOOST].end(), '_', '.');
233  names[LIB_BOOST] = "Boost";
234 
235  //
236  // Lua
237  //
238 
240  names[LIB_LUA] = "Lua";
241 
242  //
243  // OpenSSL/libcrypto
244  //
245 
246 #ifndef __APPLE__
247  compiled[LIB_CRYPTO] = format_openssl_version(OPENSSL_VERSION_NUMBER);
248  linked[LIB_CRYPTO] = format_openssl_version(SSLeay());
249  names[LIB_CRYPTO] = "OpenSSL/libcrypto";
250 #endif
251 
252  //
253  // Cairo
254  //
255 
256  compiled[LIB_CAIRO] = CAIRO_VERSION_STRING;
257  linked[LIB_CAIRO] = cairo_version_string();
258  names[LIB_CAIRO] = "Cairo";
259 
260  //
261  // Pango
262  //
263 
264  compiled[LIB_PANGO] = PANGO_VERSION_STRING;
265  linked[LIB_PANGO] = pango_version_string();
266  names[LIB_PANGO] = "Pango";
267 
268  //
269  // Features table.
270  //
271 
272  features.emplace_back(N_("feature^Lua console completion"));
273 #ifdef HAVE_HISTORY
274  features.back().enabled = true;
275 #endif
276 
277 #ifdef _X11
278 
279  features.emplace_back(N_("feature^D-Bus notifications back end"));
280 #ifdef HAVE_LIBDBUS
281  features.back().enabled = true;
282 #endif
283 
284 #endif /* _X11 */
285 
286 #ifdef _WIN32
287  // Always compiled in.
288  features.emplace_back(N_("feature^Win32 notifications back end"));
289  features.back().enabled = true;
290 #endif
291 
292 #ifdef __APPLE__
293  // Always compiled in.
294  features.emplace_back(N_("feature^Cocoa notifications back end"));
295  features.back().enabled = true;
296 #endif /* __APPLE__ */
297 }
298 
299 const std::string empty_version = "";
300 
301 } // end anonymous namespace 1
302 
303 std::string build_arch()
304 {
305 #if BOOST_ARCH_X86_64
306  return "x86_64";
307 #elif BOOST_ARCH_X86_32
308  return "x86";
309 #elif BOOST_ARCH_ARM && (defined(__arm64) || defined(_M_ARM64))
310  return "arm64";
311 #elif BOOST_ARCH_ARM
312  return "arm";
313 #elif BOOST_ARCH_IA64
314  return "ia64";
315 #elif BOOST_ARCH_PPC
316  return "ppc";
317 #elif BOOST_ARCH_ALPHA
318  return "alpha";
319 #elif BOOST_ARCH_MIPS
320  return "mips";
321 #elif BOOST_ARCH_SPARC
322  return "sparc";
323 #else
324  // Congratulations, you're running Wesnoth on an exotic platform -- either that or you live in
325  // the foretold future where x86 and ARM stopped being the dominant CPU architectures for the
326  // general-purpose consumer market. If you want to add label support for your platform, check
327  // out the Boost.Predef library's documentation and alter the code above accordingly.
328  //
329  // On the other hand, if you got here looking for Wesnoth's biggest secret let me just say
330  // right here and now that Irdya is round. There, I said the thing that nobody has dared say
331  // in mainline content before.
332  return _("cpu_architecture^<unknown>");
333 #endif
334 }
335 
336 std::vector<optional_feature> optional_features_table(bool localize)
337 {
338  std::vector<optional_feature> res = versions.features;
339 
340  for(std::size_t k = 0; k < res.size(); ++k) {
341  if(localize) {
342  res[k].name = _(res[k].name.c_str());
343  } else {
344  // Strip annotation carets ("blah blah^actual text here") from translatable
345  // strings.
346  const auto caret_pos = res[k].name.find('^');
347  if(caret_pos != std::string::npos) {
348  res[k].name.erase(0, caret_pos + 1);
349  }
350  }
351  }
352  return res;
353 }
354 
355 const std::string& library_build_version(LIBRARY_ID lib)
356 {
357  if(lib >= LIB_COUNT) {
358  return empty_version;
359  }
360 
361  return versions.compiled[lib];
362 }
363 
364 const std::string& library_runtime_version(LIBRARY_ID lib)
365 {
366  if(lib >= LIB_COUNT) {
367  return empty_version;
368  }
369 
370  return versions.linked[lib];
371 }
372 
373 const std::string& library_name(LIBRARY_ID lib)
374 {
375  if(lib >= LIB_COUNT) {
376  return empty_version;
377  }
378 
379  return versions.names[lib];
380 }
381 
382 std::string dist_channel_id()
383 {
384  std::string info;
385  std::ifstream infofile(game_config::path + "/data/dist");
386  if(infofile.is_open()) {
387  std::getline(infofile, info);
388  infofile.close();
389  boost::trim(info);
390  }
391 
392  if(info.empty()) {
393  return "Default";
394  }
395 
396  return info;
397 }
398 
399 namespace {
400 
401 /**
402  * Formats items into a tidy 2-column list with a fixed-length first column.
403  */
404 class list_formatter
405 {
406 public:
407  using list_entry = std::pair<std::string, std::string>;
408  using contents_list = std::vector<list_entry>;
409 
410  list_formatter(const std::string& heading, const contents_list& contents = {}, const std::string& empty_placeholder = "")
411  : heading_(heading)
412  , placeholder_(empty_placeholder)
413  , contents_(contents)
414  {
415  }
416 
417  void insert(const std::string& label, const std::string& value)
418  {
419  contents_.emplace_back(label, value);
420  }
421 
422  void set_placeholder(const std::string& placeholder)
423  {
424  placeholder_ = placeholder;
425  }
426 
427  void stream_put(std::ostream& os) const;
428 
429 private:
430  static const char heading_delimiter;
431  static const std::string label_delimiter;
432 
433  std::string heading_;
434  std::string placeholder_;
435 
436  contents_list contents_;
437 };
438 
439 const char list_formatter::heading_delimiter = '=';
440 const std::string list_formatter::label_delimiter = ": ";
441 
442 void list_formatter::stream_put(std::ostream& os) const
443 {
444  if(!heading_.empty()) {
445  os << heading_ << '\n' << std::string(utf8::size(heading_), heading_delimiter) << "\n\n";
446  }
447 
448  if(contents_.empty() && !placeholder_.empty()) {
449  os << placeholder_ << '\n';
450  } else if(!contents_.empty()) {
451  auto label_length_comparator = [](const list_entry& a, const list_entry& b)
452  {
453  return utf8::size(a.first) < utf8::size(b.first);
454  };
455 
456  const auto longest_entry_label = std::max_element(contents_.begin(), contents_.end(), label_length_comparator);
457  const std::size_t min_length = longest_entry_label != contents_.end()
458  ? utf8::size(label_delimiter) + utf8::size(longest_entry_label->first)
459  : 0;
460 
461  // Save stream attributes for resetting them later after completing the loop
462  const std::size_t prev_width = os.width();
463  const std::ostream::fmtflags prev_flags = os.flags();
464 
465  os << std::left;
466 
467  for(const auto& entry : contents_) {
468  os << std::setw(min_length) << entry.first + label_delimiter << entry.second << '\n';
469  }
470 
471  os.width(prev_width);
472  os.flags(prev_flags);
473  }
474 
475  os << '\n';
476 }
477 
478 std::ostream& operator<<(std::ostream& os, const list_formatter& fmt)
479 {
480  fmt.stream_put(os);
481  return os;
482 }
483 
484 list_formatter library_versions_report_internal(const std::string& heading = "")
485 {
486  list_formatter fmt{heading};
487 
488  for(unsigned n = 0; n < LIB_COUNT; ++n)
489  {
490  if(versions.names[n].empty()) {
491  continue;
492  }
493 
494  std::string text = versions.compiled[n];
495  if(!versions.linked[n].empty()) {
496  text += " (runtime " + versions.linked[n] + ")";
497  }
498 
499  fmt.insert(versions.names[n], text);
500  }
501 
502  return fmt;
503 }
504 
505 list_formatter optional_features_report_internal(const std::string& heading = "")
506 {
507  list_formatter fmt{heading};
508 
509  const std::vector<optional_feature>& features = optional_features_table(false);
510 
511  for(const auto& feature : features) {
512  fmt.insert(feature.name, feature.enabled ? "yes" : "no");
513  }
514 
515  return fmt;
516 }
517 
518 template<typename T>
519 inline std::string geometry_to_string(T horizontal, T vertical)
520 {
521  return std::to_string(horizontal) + 'x' + std::to_string(vertical);
522 }
523 
524 std::string format_sdl_driver_list(std::vector<std::string> drivers, const std::string& current_driver)
525 {
526  bool found_current_driver = false;
527 
528  for(auto& drvname : drivers) {
529  if(current_driver == drvname) {
530  found_current_driver = true;
531  drvname = "[" + current_driver + "]";
532  }
533  }
534 
535  if(drivers.empty() || !found_current_driver) {
536  // This shouldn't happen but SDL is weird at times so whatevs
537  drivers.emplace_back("[" + current_driver + "]");
538  }
539 
540  return utils::join(drivers, " ");
541 }
542 
543 list_formatter video_settings_report_internal(const std::string& heading = "")
544 {
545  list_formatter fmt{heading};
546 
547  if(!CVideo::setup_completed()) {
548  fmt.set_placeholder("Graphics not initialized.");
549  return fmt;
550  }
551 
552  CVideo& video = CVideo::get_singleton();
553 
554  std::string placeholder;
555 
556  if(video.non_interactive()) {
557  placeholder = "Running in non-interactive mode.";
558  } else if(!video.has_window()) {
559  placeholder = "Running without a game window.";
560  }
561 
562  if(!placeholder.empty()) {
563  fmt.set_placeholder(placeholder);
564  return fmt;
565  }
566 
567  const auto& current_driver = CVideo::current_driver();
568  auto drivers = CVideo::enumerate_drivers();
569 
570  const auto& dpi = video.get_dpi();
571  const auto& scale = video.get_dpi_scale_factor();
572  std::string dpi_report, scale_report;
573 
574  if(dpi.first == 0.0f || dpi.second == 0.0f) {
575  scale_report = dpi_report = "<unknown>";
576  } else {
577  dpi_report = geometry_to_string(dpi.first, dpi.second);
578  scale_report = geometry_to_string(scale.first, scale.second);
579  }
580 
581  fmt.insert("SDL video drivers", format_sdl_driver_list(drivers, current_driver));
582  fmt.insert("Window size", geometry_to_string(video.get_width(), video.get_height()));
583  fmt.insert("Screen refresh rate", std::to_string(video.current_refresh_rate()));
584  fmt.insert("Screen dots per inch", dpi_report);
585  fmt.insert("Screen dpi scale factor", scale_report);
586 
587  return fmt;
588 }
589 
590 list_formatter sound_settings_report_internal(const std::string& heading = "")
591 {
592  list_formatter fmt{heading};
593 
594  const auto& driver_status = sound::driver_status::query();
595 
596  if(!driver_status.initialized) {
597  fmt.set_placeholder("Audio not initialized.");
598  return fmt;
599  }
600 
601  const auto& current_driver = sound::current_driver();
602  auto drivers = sound::enumerate_drivers();
603 
604  static std::map<uint16_t, std::string> audio_format_names = {
605  // 8 bits
606  { AUDIO_U8, "unsigned 8 bit" },
607  { AUDIO_S8, "signed 8 bit" },
608  // 16 bits
609  { AUDIO_U16LSB, "unsigned 16 bit little-endian" },
610  { AUDIO_U16MSB, "unsigned 16 bit big-endian" },
611  { AUDIO_S16LSB, "signed 16 bit little-endian" },
612  { AUDIO_S16MSB, "signed 16 bit big-endian" },
613  // 32 bits
614  { AUDIO_S32LSB, "signed 32 bit little-endian" },
615  { AUDIO_S32MSB, "signed 32 bit big-endian" },
616  { AUDIO_F32LSB, "signed 32 bit floating point little-endian" },
617  { AUDIO_F32MSB, "signed 32 bit floating point big-endian" },
618  };
619 
620  auto fmt_names_it = audio_format_names.find(driver_status.format);
621  // If we don't recognize the format id just print the raw number
622  const std::string fmt_name = fmt_names_it != audio_format_names.end()
623  ? fmt_names_it->second
624  : formatter() << "0x" << std::setfill('0') << std::setw(2*sizeof(driver_status.format)) << std::hex << std::uppercase << driver_status.format;
625 
626  fmt.insert("SDL audio drivers", format_sdl_driver_list(drivers, current_driver));
627  fmt.insert("Number of channels", std::to_string(driver_status.channels));
628  fmt.insert("Output rate", std::to_string(driver_status.frequency) + " Hz");
629  fmt.insert("Sample format", fmt_name);
630  fmt.insert("Sample size", std::to_string(driver_status.chunk_size) + " bytes");
631 
632  return fmt;
633 }
634 
635 } // end anonymous namespace 2
636 
638 {
639  return formatter{} << library_versions_report_internal();
640 }
641 
643 {
644  return formatter{} << optional_features_report_internal();
645 }
646 
647 std::string full_build_report()
648 {
649  list_formatter::contents_list paths{
650  {"Data dir", game_config::path},
651  {"User config dir", filesystem::get_user_config_dir()},
652  {"User data dir", filesystem::get_user_data_dir()},
653  {"Saves dir", filesystem::get_saves_dir()},
654  {"Add-ons dir", filesystem::get_addons_dir()},
655  {"Cache dir", filesystem::get_cache_dir()},
656  };
657 
658  // Obfuscate usernames in paths
659  for(auto& entry : paths) {
660  entry.second = filesystem::sanitize_path(entry.second);
661  }
662 
663  list_formatter::contents_list addons;
664 
665  for(const auto& addon_info : installed_addons_and_versions()) {
666  addons.emplace_back(addon_info.first, addon_info.second);
667  }
668 
669  std::ostringstream o;
670 
671  o << "The Battle for Wesnoth version " << game_config::revision << " " << build_arch() << '\n'
672  << "Running on " << desktop::os_version() << '\n'
673  << "Distribution channel: " << dist_channel_id() << '\n'
674  << '\n'
675  << list_formatter{"Game paths", paths}
676  << library_versions_report_internal("Libraries")
677  << optional_features_report_internal("Features")
678  << video_settings_report_internal("Current video settings")
679  << sound_settings_report_internal("Current audio settings")
680  << list_formatter("Installed add-ons", addons, "No add-ons installed.");
681 
682  return o.str();
683 }
684 
685 } // end namespace game_config
std::string heading_
Definition: build_info.cpp:433
static const char heading_delimiter
Definition: build_info.cpp:430
std::string library_versions_report()
Produce a plain-text report of library versions suitable for stdout/stderr.
Definition: build_info.cpp:637
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::string current_driver()
Definition: sound.cpp:412
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::pair< float, float > get_dpi_scale_factor() const
The current scale factor on High-DPI screens.
Definition: video.cpp:416
static const std::string label_delimiter
Definition: build_info.cpp:431
std::string optional_features_report()
Produce a plain-text report of features suitable for stdout/stderr.
Definition: build_info.cpp:642
logger & info()
Definition: log.cpp:89
#define a
std::string placeholder_
Definition: build_info.cpp:434
Definition: video.hpp:32
contents_list contents_
Definition: build_info.cpp:436
static CVideo & get_singleton()
Definition: video.hpp:49
bool non_interactive() const
Definition: video.cpp:135
STL namespace.
const std::string & library_build_version(LIBRARY_ID lib)
Retrieve the build-time version number of the given library.
Definition: build_info.cpp:355
std::vector< optional_feature > optional_features_table(bool localize)
Retrieve the features table.
Definition: build_info.cpp:336
static std::string _(const char *str)
Definition: gettext.hpp:93
std::string get_saves_dir()
#define b
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
const std::string & library_name(LIBRARY_ID lib)
Retrieve the user-visible name for the given library.
Definition: build_info.cpp:373
void scale(size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, const ScalerCfg &cfg=ScalerCfg(), int yFirst=0, int yLast=std::numeric_limits< int >::max())
Definition: xbrz.cpp:1190
std::string label
What to show in the filter&#39;s drop-down list.
Definition: manager.cpp:217
std::vector< optional_feature > features
Definition: build_info.cpp:67
std::ostringstream wrapper.
Definition: formatter.hpp:39
std::string get_user_data_dir()
Definition: filesystem.cpp:792
static std::vector< std::string > enumerate_drivers()
Definition: video.cpp:365
std::string dist_channel_id()
Return the distribution channel identifier, or "Default" if missing.
Definition: build_info.cpp:382
std::string path
Definition: game_config.cpp:39
std::string build_arch()
Obtain the processor architecture for this build.
Definition: build_info.cpp:303
std::string sanitize_path(const std::string &path)
Sanitizes a path to remove references to the user&#39;s name.
int get_width(bool as_pixels=true) const
Returns the window renderer width in pixels or screen coordinates.
Definition: video.cpp:291
bool has_window()
Definition: video.hpp:81
std::ostream & operator<<(std::ostream &s, const ai::attack_result &r)
Definition: actions.cpp:1135
#define LUA_VERSION_MINOR
Definition: lua.h:20
Platform identification and version information functions.
std::string get_cache_dir()
Definition: filesystem.cpp:797
int current_refresh_rate() const
Definition: video.hpp:165
std::vector< std::string > linked
Definition: build_info.cpp:66
const std::string revision
mock_party p
Game configuration data as global variables.
Definition: build_info.cpp:59
#define LUA_VERSION_RELEASE
Definition: lua.h:21
std::string os_version()
Returns a string with the running OS name and version information.
Definition: version.cpp:213
#define LUA_VERSION_MAJOR
Definition: lua.h:19
std::vector< std::string > names
Definition: build_info.cpp:66
const std::string & library_runtime_version(LIBRARY_ID lib)
Retrieve the runtime version number of the given library.
Definition: build_info.cpp:364
static std::string current_driver()
Definition: video.cpp:359
std::string & insert(std::string &str, const std::size_t pos, const std::string &insert)
Insert a UTF-8 string at the specified position.
Definition: unicode.cpp:100
Declarations for File-IO.
int get_height(bool as_pixels=true) const
Returns the window renderer height in pixels or in screen coordinates.
Definition: video.cpp:296
#define N_(String)
Definition: gettext.hpp:101
std::string get_user_config_dir()
Definition: filesystem.cpp:763
lu_byte left
Definition: lparser.cpp:1226
std::string get_addons_dir()
void trim(std::string_view &s)
static driver_status query()
Definition: sound.cpp:431
mock_char c
std::vector< std::string > enumerate_drivers()
Definition: sound.cpp:418
static map_location::DIRECTION n
std::vector< std::string > compiled
Definition: build_info.cpp:66
static bool setup_completed()
Definition: video.hpp:44
std::string full_build_report()
Produce a bug report-style info dump.
Definition: build_info.cpp:647
std::pair< float, float > get_dpi() const
The current game screen dpi.
Definition: video.cpp:387
std::map< std::string, std::string > installed_addons_and_versions()
Retrieves the ids and versions of all installed add-ons.
Definition: manager.cpp:183