17 #define GETTEXT_DOMAIN "wesnoth-lib" 
   72 void disable_widget_on_toggle(window& window, widget& 
w, 
const std::string& 
id)
 
   74     window.find_widget<W>(
id).set_active(
dynamic_cast<selectable_item&
>(
w).get_value_bool());
 
   78 void disable_widget_on_toggle_inverted(window& window, widget& 
w, 
const std::string& 
id)
 
   80     window.find_widget<W>(
id).set_active(!
dynamic_cast<selectable_item&
>(
w).get_value_bool());
 
   85 int index_in_pager_range(
const int first, 
const stacked_widget& pager)
 
   87     return std::clamp<int>(first, 0, pager.get_layer_count() - 1);
 
   91 template<
bool(*fptr)(
bool)>
 
   92 void sound_toggle_on_change(window& window, 
const std::string& id_to_toggle, widget& 
w)
 
   94     std::invoke(fptr, 
dynamic_cast<selectable_item&
>(
w).get_value_bool());
 
   97     disable_widget_on_toggle<slider>(window, 
w, id_to_toggle);
 
  101 template<
void(*fptr)(
int)>
 
  102 void volume_setter_on_change(widget& 
w)
 
  104     std::invoke(fptr, 
dynamic_cast<integer_selector&
>(
w).get_value());
 
  116     , last_selected_item_(0)
 
  117     , current_gui_theme_(0)
 
  118     , is_reload_needed_(false)
 
  119     , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
 
  121     , visible_categories_()
 
  122     , initial_index_(pef_view_map[initial_view])
 
  124     initialize_callbacks();
 
  132     std::vector<config> options;
 
  137         const int div = std::gcd(res.x, res.y);
 
  138         const int x_ratio = res.x / div;
 
  139         const int y_ratio = res.y / div;
 
  141         if(x_ratio <= 10 || y_ratio <= 10) {
 
  145         options.push_back(std::move(option));
 
  158     std::vector<config> options;
 
  159     std::size_t current_theme = 0;
 
  160     for(std::size_t 
i = 0; 
i < 
themes_.size(); ++
i) {
 
  161         options.emplace_back(
"label", 
themes_[
i].name, 
"tooltip", 
themes_[
i].description);
 
  167     theme_list.set_values(options, current_theme);
 
  172     std::string current_gui_theme_name = 
prefs::get().gui2_theme();
 
  174     std::vector<config> options;
 
  175     bool theme_found = 
false;
 
  179         options.emplace_back(
"label", 
gui.second.description());
 
  180         if (current_gui_theme_name == 
gui.first) {
 
  198     std::string 
image = 
"friend.png";
 
  199     std::string descriptor = 
_(
"friend");
 
  203         image = 
"ignore.png";
 
  204         descriptor = 
_(
"ignored");
 
  211     item[
"use_markup"] = 
"true";
 
  213     item[
"label"] = 
"misc/status-" + 
image;
 
  214     data.emplace(
"friend_icon", item);
 
  216     item[
"label"] = entry.
get_nick() + notes;
 
  217     data.emplace(
"friend_name", item);
 
  220     data.emplace(
"friend_status", item);
 
  230     if(sel < 0 || sel >= num_friends) {
 
  235     std::advance(who, sel);
 
  237     textbox.
set_value(who->second.get_nick() + 
" " + who->second.get_notes());
 
  248     find_widget<button>(
"remove").set_active(!list_empty);
 
  250     find_widget<label>(
"no_friends_notice").set_visible(list_empty);
 
  255     std::string username = textbox.
text();
 
  256     if(username.empty()) {
 
  263     std::size_t pos = username.find_first_of(
' ');
 
  264     if(pos != std::string::npos) {
 
  265         reason = username.substr(pos + 1);
 
  266         username = username.substr(0, pos);
 
  278     listbox& list = find_widget<listbox>(
"friends_list");
 
  309     std::advance(who, selected_row);
 
  311     const std::string to_remove = !textbox.
text().empty() ? textbox.
text() : who->second.get_nick();
 
  313     if(to_remove.empty()) {
 
  318     if(!
prefs::get().remove_acquaintance(to_remove)) {
 
  325     listbox& list = find_widget<listbox>(
"friends_list");
 
  334     slider& ps_slider = find_widget<slider>(
"pixel_scale_slider");
 
  339         find_widget<toggle_button>(
"auto_pixel_scale");
 
  347         disp->queue_rerender();
 
  354 template<
bool(*toggle_getter)(), 
bool(*toggle_setter)(
bool), 
int(*vol_getter)(), 
void(*vol_setter)(
int)>
 
  357     const std::string toggle_widget_id = 
"sound_toggle_" + id_suffix;
 
  358     const std::string volume_widget_id = 
"sound_volume_" + id_suffix;
 
  360     const auto on_changed = [
this, volume_widget_id](
widget& 
w) {
 
  361         sound_toggle_on_change<toggle_setter>(*
this, volume_widget_id, 
w);
 
  369     register_bool(toggle_widget_id, 
true, toggle_getter, toggle_setter, on_changed, 
true);
 
  378         [](
widget& 
w, 
auto&&...) { volume_setter_on_change<vol_setter>(
w); });
 
  424     const auto accl_load = [
this]()->
int {
 
  428     const auto accl_save = [
this](
int i) {
 
  433         accl_load, accl_save);
 
  436     find_widget<slider>(
"turbo_slider").set_value_labels(
 
  444         [](
bool v) {
prefs::get().set_skip_ai_moves(v);});
 
  448         []() {
return prefs::get().disable_auto_moves();},
 
  449         [](
bool v) {
prefs::get().set_disable_auto_moves(v);});
 
  454         [](
bool v) {
prefs::get().set_turn_dialog(v);});
 
  458         []() {
return prefs::get().enable_planning_mode_on_start();},
 
  459         [](
bool v) {
prefs::get().set_enable_planning_mode_on_start(v);});
 
  463         []() {
return prefs::get().hide_whiteboard();},
 
  464         [](
bool v) {
prefs::get().set_hide_whiteboard(v);});
 
  468         []() {
return prefs::get().ally_sighted_interrupts();},
 
  469         [](
bool v) {
prefs::get().set_ally_sighted_interrupts(v);});
 
  474         [](
bool v) {
prefs::get().set_save_replays(v);});
 
  479         [](
bool v) {
prefs::get().set_delete_saves(v);});
 
  484         [](
int v) {
prefs::get().set_auto_save_max(v);});
 
  488         [](
auto&&...) { dialogs::game_cache_options::display(); });
 
  506     menu_button& res_list = find_widget<menu_button>(
"resolution_set");
 
  508     res_list.set_use_markup(
true);
 
  510     res_list.set_active(
false);
 
  512     res_list.set_active(!
prefs::get().fullscreen());
 
  520     connect_signal<event::SDL_VIDEO_RESIZE>(
 
  529         slider& ps_slider = find_widget<slider>(
"pixel_scale_slider");
 
  536             []() {
return prefs::get().auto_pixel_scale();},
 
  537             [](
bool v) {
prefs::get().set_auto_pixel_scale(v);},
 
  538             [&](
widget& 
w) { disable_widget_on_toggle_inverted<slider>(*
this, 
w, 
"pixel_scale_slider"); }, 
true);
 
  540         find_widget<slider>(
"pixel_scale_slider").set_active(
false);
 
  541         find_widget<toggle_button>(
"auto_pixel_scale").set_active(
false);
 
  545         find_widget<toggle_button>(
"auto_pixel_scale");
 
  561         []() {
return prefs::get().floating_labels();},
 
  562         [](
bool v) {
prefs::get().set_floating_labels(v);});
 
  566         []() {
return prefs::get().show_side_colors();},
 
  567         [](
bool v) {
prefs::get().set_show_side_colors(v);});
 
  577         [](
bool v) {
prefs::get().set_animate_map(v);},
 
  578         [&](
widget& 
w) { disable_widget_on_toggle<toggle_button>(*
this, 
w, 
"animate_water"); }, 
true);
 
  583         [](
bool v) {
prefs::get().set_animate_water(v);});
 
  594         [&](
widget& 
w) { disable_widget_on_toggle<slider>(*
this, 
w, 
"idle_anim_frequency"); }, 
true);
 
  598         [](
int v) {
prefs::get().set_idle_anim_rate(v);});
 
  616     menu_button& gui2_theme_list = find_widget<menu_button>(
"choose_gui2_theme");
 
  617     button& apply_btn = find_widget<button>(
"apply");
 
  629     initialize_sound_option_group<sound, set_sound, sound_volume, set_sound_volume>(
"sfx");
 
  632     initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>(
"music");
 
  635         []() {
return prefs::get().stop_music_in_background();},
 
  636         [](
bool v) {
prefs::get().set_stop_music_in_background(v);});
 
  639     initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>(
"bell");
 
  642     initialize_sound_option_group<ui_sound_on, set_ui_sound, ui_volume, set_ui_volume>(
"uisfx");
 
  656         [](
bool v) {
prefs::get().set_chat_timestamp(v);});
 
  665         []() {
return prefs::get().lobby_whisper_friends_only();},
 
  666         [](
bool v) {
prefs::get().set_lobby_whisper_friends_only(v);});
 
  680     listbox& friends_list = find_widget<listbox>(
"friends_list");
 
  682     friends_list.
clear();
 
  684     for(
const auto& entry : 
prefs::get().get_acquaintances()) {
 
  690     text_box& textbox = find_widget<text_box>(
"friend_name_box");
 
  706         [](
auto&&...) { mp_alerts_options::display(); });
 
  717     listbox& advanced = find_widget<listbox>(
"advanced_prefs");
 
  721     for(
const auto& option : 
prefs::get().get_advanced_preferences()) {
 
  722         const std::string pref_name = option.field;
 
  724         row_data[
"pref_name"][
"label"] = option.name;
 
  734         if(!option.description.empty()) {
 
  738         switch(option.type) {
 
  752                 auto setter_widget = build_single_widget_instance<slider>(
config {
"definition", 
"minimal"});
 
  753                 setter_widget->set_id(
"setter");
 
  755                 setter_widget->set_value_range(option.cfg[
"min"].to_int(), option.cfg[
"max"].to_int());
 
  756                 setter_widget->set_step_size(option.cfg[
"step"].to_int(1));
 
  758                 details_grid.
swap_child(
"setter", std::move(setter_widget), 
true);
 
  772                 std::vector<config> menu_data;
 
  773                 std::vector<std::string> option_ids;
 
  777                     menu_item[
"label"] = choice[
"name"];
 
  778                     if(choice.has_attribute(
"description")) {
 
  781                     menu_data.push_back(menu_item);
 
  782                     option_ids.push_back(choice[
"id"]);
 
  786                 int selected = std::distance(option_ids.begin(), 
std::find(option_ids.begin(), option_ids.end(),
 
  791                 if(selected < 0 || selected >= 
static_cast<int>(option_ids.size())) {
 
  795                 auto setter_widget = build_single_widget_instance<menu_button>();
 
  796                 setter_widget->set_id(
"setter");
 
  798                 details_grid.
swap_child(
"setter", std::move(setter_widget), 
true);
 
  815                 auto value_widget = build_single_widget_instance<image>();
 
  816                 value_widget->set_label(
"icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
 
  818                 main_grid->
swap_child(
"value", std::move(value_widget), 
true);
 
  833     multimenu_button& hotkey_menu = find_widget<multimenu_button>(
"hotkey_category_menu");
 
  855     hotkey_list.set_active_sorter(
"sort_0", sort_order::type::ascending, 
true);
 
  871     t_string& row_icon   = row_data[
"img_icon"][
"label"];
 
  872     t_string& row_action = row_data[
"lbl_desc"][
"label"];
 
  873     t_string& row_hotkey = row_data[
"lbl_hotkey"][
"label"];
 
  875     t_string& row_is_g   = row_data[
"lbl_is_game"][
"label"];
 
  876     t_string& row_is_e   = row_data[
"lbl_is_editor"][
"label"];
 
  877     t_string& row_is_m   = row_data[
"lbl_is_mainmenu"][
"label"];
 
  895         if(hotkey_item.hidden) {
 
  903             row_icon = 
"icons/action/" + hotkey_item.id + 
"_25.png~CROP(3,3,18,18)";
 
  908         row_action = hotkey_item.description;
 
  922     std::vector<config> filter_ops;
 
  927     find_widget<multimenu_button>(
"hotkey_category_menu").set_values(filter_ops);
 
  949     if(newhk.get() == 
nullptr) {
 
  954         if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
 
  959     if(oldhk && oldhk->get_command() == hotkey_item.
id) {
 
  963     if(oldhk && oldhk->get_command() != 
"null") {
 
  964         const std::string text = 
VGETTEXT(
"“<b>$hotkey_sequence|</b>” is in use by “<b>$old_hotkey_action|</b>”.\nDo you wish to reassign it to “<b>$new_hotkey_action|</b>”?", {
 
  965             {
"hotkey_sequence",   oldhk->get_name()},
 
  993     hotkey_list.set_active_sorter(
"sort_0", sort_order::type::ascending, 
true);
 
 1011     const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(
"hotkey_category_menu");
 
 1012     const text_box& name_filter = find_widget<const text_box>(
"filter");
 
 1017     std::string text = name_filter.
get_value();
 
 1020     if(toggle_states.none()) {
 
 1021         toggle_states = ~toggle_states;
 
 1041         unsigned cat_index = 0;
 
 1052         if(cat_index < toggle_states.size() && found) {
 
 1053             res[
h] = toggle_states[cat_index];
 
 1059     find_widget<listbox>(
"list_hotkeys").set_row_shown(res);
 
 1068         if(pref.field == 
"logging") {
 
 1069             gui2::dialogs::log_settings::display();
 
 1070         } 
else if(pref.field == 
"orb_color") {
 
 1071             gui2::dialogs::select_orb_colors::display();
 
 1072         } 
else if(pref.field == 
"reach_map") {
 
 1073             gui2::dialogs::reachmap_options::display();
 
 1075             WRN_GUI_L << 
"Invalid or unimplemented custom advanced prefs option: " << pref.field;
 
 1081     const bool has_description = !pref.description.empty();
 
 1110         [](
auto&&...) { game_version::display(); });
 
 1122     listbox& selector = find_widget<listbox>(
"selector");
 
 1133         "The preferences pager and its selector listbox do not have the same number of items.");
 
 1135     const int main_index = index_in_pager_range(
initial_index_.first, pager);
 
 1145         if(tab_pager && tab_selector) {
 
 1146             const int ii = 
static_cast<int>(
i);
 
 1147             const int tab_index = index_in_pager_range(
initial_index_.second, *tab_pager);
 
 1148             const int to_select = (ii == main_index ? tab_index : 0);
 
 1154             tab_pager->select_layer(to_select);
 
 1165     find_widget<stacked_widget>(pager_id).select_layer(page);
 
 1171     const bool ison = find_widget<toggle_button>(
"fullscreen").get_value_bool();
 
 1174     menu_button& res_list = find_widget<menu_button>(
"resolution_set");
 
 1182     menu_button& res_list = find_widget<menu_button>(
"resolution_set");
 
 1193     const auto selection = 
theme_list.get_value();
 
 1206     menu_button& gui2_theme_list = find_widget<menu_button>(
"choose_gui2_theme");
 
 1207     unsigned selected_theme = gui2_theme_list.
get_value();
 
 1217     const int selected_row =
 
 1218         std::max(0, find_widget<listbox>(
"selector").get_selected_row());
 
 1224     const int selected_row =
 
 1225         std::max(0, find_widget<listbox>(
"tab_selector").get_selected_row());
 
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(std::string_view key)
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
void set_theme(const std::string &new_theme)
static display * get_singleton()
Returns the display object if a display object exists.
hotkey::hotkey_ptr get_new_binding() const
@ yes_no_buttons
Shows a yes and no button.
Abstract base class for all modal dialogs.
field_bool * register_bool(const std::string &id, const bool mandatory, const std::function< bool()> &callback_load_value=nullptr, const std::function< void(bool)> &callback_save_value=nullptr, const std::function< void(widget &)> &callback_change=nullptr, const bool initial_fire=false)
Creates a new boolean field.
void set_always_save_fields(const bool always_save_fields)
field_integer * register_integer(const std::string &id, const bool mandatory, const std::function< int()> &callback_load_value=nullptr, const std::function< void(int)> &callback_save_value=nullptr)
Creates a new integer field.
bool show(const unsigned auto_close_time=0)
Shows the window.
void set_visible_page(unsigned int page, const std::string &pager_id)
void set_theme_list(menu_button &theme_list)
void remove_hotkey_callback(listbox &hotkeys)
const std::pair< int, int > & initial_index_
void initialize_tabs(listbox &selector)
void set_resolution_list(menu_button &res_list)
void on_advanced_prefs_list_select(listbox &tree)
unsigned current_gui_theme_
void handle_gui2_theme_select()
void default_hotkey_callback()
void on_page_select()
Callback for selection changes.
void on_friends_list_select(listbox &list, text_box &textbox)
void hotkey_filter_callback()
void add_friend_list_entry(const bool is_friend, text_box &textbox)
void handle_theme_select()
std::vector< double > accl_speeds_
std::vector< const hotkey::hotkey_command * > visible_hotkeys_
std::vector< theme_info > themes_
widget_data get_friends_list_row_data(const preferences::acquaintance &entry)
virtual void post_show() override
Actions to be taken after the window has been shown.
std::set< hotkey::HOTKEY_CATEGORY > visible_categories_
void update_friends_list_controls(listbox &list)
void handle_res_select()
Special callback functions.
void fullscreen_toggle_callback()
std::vector< std::string > gui2_themes_
virtual void pre_show() override
Actions to be taken before showing the window.
listbox & setup_hotkey_list()
void remove_friend_list_entry(listbox &friends_list, text_box &textbox)
void initialize_sound_option_group(const std::string &id_suffix)
void add_hotkey_callback(listbox &hotkeys)
group< pref_constants::lobby_joins > lobby_joins_group
void initialize_callbacks()
Initializers.
void set_gui2_theme_list(menu_button &theme_list)
std::vector< point > resolutions_
std::unique_ptr< widget > swap_child(const std::string &id, std::unique_ptr< widget > w, const bool recurse, widget *new_parent=nullptr)
Exchanges a child in the grid.
unsigned add_row(const unsigned count=1)
Adds a row to end of the grid.
void on_modified(const Func &func)
Sets a common callback function for all members.
void add_member(selectable_item *w, const T &value)
Adds a widget/value pair to the group map.
void set_member_states(const T &value)
Sets the toggle values for all widgets besides the one associated with the specified value to false.
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
bool select_row(const unsigned row, const bool select=true)
Selects a row.
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
void clear()
Removes all the rows in the listbox, clearing it.
int get_selected_row() const
Returns the first selected row.
unsigned get_item_count() const
Returns the number of items in the listbox.
bool get_value_bool() const
virtual void set_value(int value) override
Inherited from integer_selector.
virtual int get_value() const override
Inherited from integer_selector.
std::string get_value() const
const std::string & text() const
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
A widget that allows the user to input text in single line.
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
void keyboard_capture(widget *widget)
const std::string & get_status() const
const std::string & get_nick() const
const std::string & get_notes() const
void set_lobby_joins(pref_constants::lobby_joins show)
bool set_music(bool ison)
void set_sound_volume(int vol)
void set_remember_password(bool remember)
const std::map< std::string, preferences::acquaintance > & get_acquaintances()
void set_turbo(bool ison)
bool set_ui_sound(bool ison)
void set_theme(const std::string &theme)
void show_wesnothd_server_search()
bool set_turn_bell(bool ison)
void set_music_volume(int vol)
void set_show_standing_animations(bool value)
void set_pixel_scale(const int scale)
pref_constants::lobby_joins get_lobby_joins()
bool set_sound(bool ison)
void set_scroll_speed(const int scroll)
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string ¬es)
void set_ui_volume(int vol)
void set_bell_volume(int vol)
const std::vector< preferences::option > & get_advanced_preferences()
bool show_standing_animations()
static std::vector< theme_info > get_basic_theme_info(bool include_hidden=false)
Returns minimal info about saved themes, optionally including hidden ones.
map_display and display: classes which take care of displaying the map and game-data on the screen.
Declarations for File-IO.
static std::string _(const char *str)
std::string id
Text to match against addon_info.tags()
New lexcical_cast header.
void raise_resize_event()
static bool file_exists(const bfs::path &fpath)
const std::string unicode_multiplication_sign
static void set_sound_volume(int v)
static bool set_sound(bool v)
static bool set_music(bool v)
static bool set_ui_sound(bool v)
static int music_volume()
static void set_bell_volume(int v)
static void set_ui_volume(int v)
static void set_music_volume(int v)
REGISTER_DIALOG(editor_edit_unit)
static bool set_turn_bell(bool v)
static bool ui_sound_on()
static int sound_volume()
void connect_signal_mouse_left_release(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button release.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
void bind_default_status_label(W &source)
Binds a status label using the default value getter and default target ID.
gui_theme_map_t guis
Map of all known GUIs.
std::map< std::string, widget_item > widget_data
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
std::map< std::string, t_string > widget_item
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
@ OK
Dialog was closed with the OK button.
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
std::shared_ptr< class hotkey_base > hotkey_ptr
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
const std::map< std::string_view, hotkey::hotkey_command > & get_hotkey_commands()
returns a container that contains all currently active hotkey_commands.
const hotkey_command & get_hotkey_command(std::string_view command)
Returns the hotkey_command with the given id.
std::vector< hotkey::hotkey_ptr > hotkey_list
void add_hotkey(hotkey_ptr item)
Add a hotkey to the list of hotkeys.
t_string get_translatable_category_name(HOTKEY_CATEGORY category)
Gets the display name for a given hotkey category.
Functions to load and save images from/to disk.
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
bool ci_search(const std::string &s1, const std::string &s2)
Case-insensitive search.
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
std::vector< point > get_available_resolutions(const bool include_current)
Returns the list of available screen resolutions.
int get_max_pixel_scale()
point current_resolution()
The current window size in desktop coordinates.
void set_fullscreen(bool fullscreen)
Set the fullscreen state.
bool set_resolution(const point &resolution)
Set the window resolution.
void toggle_fullscreen()
Toggle fullscreen mode.
void update_buffers(bool autoupdate)
Update buffers to match current resolution and pixel scale settings.
Stores all information related to functions that can be bound to hotkeys.
std::string id
The unique ID.
static bool get(const std::string &pref, bool def)
static void set(const std::string &pref, bool value)
Definitions related to theme-support.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define VALIDATE(cond, message)
The macro to use for the validation of WML.