wesnoth/src/preferences.cpp

985 lines
19 KiB
C++

/* $Id$ */
/*
Copyright (C) 2003 by David White <davidnwhite@verizon.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "global.hpp"
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "config.hpp"
#include "filesystem.hpp"
#include "gamestatus.hpp"
#include "gettext.hpp"
#include "hotkeys.hpp"
#include "log.hpp"
#include "preferences.hpp"
#include "sound.hpp"
#include "util.hpp"
#include "video.hpp" // non_interactive()
#include "wesconfig.h"
#include "serialization/parser.hpp"
#include "serialization/string_utils.hpp"
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <sstream>
namespace {
config prefs;
bool colour_cursors = false;
bool message_private_on = true;
bool haloes = true;
bool unit_genders = true;
bool fps = false;
std::set<std::string> encountered_units_set;
std::set<std::string> encountered_terrains_set;
}
namespace preferences {
manager::manager()
{
scoped_istream stream = istream_file(get_prefs_file());
read(prefs, *stream);
set_music_volume(music_volume());
set_sound_volume(sound_volume());
set_show_haloes(prefs["show_haloes"] != "no");
if(prefs["remember_timer_settings"] != "yes") {
prefs.values.erase("mp_countdown_init_time");
prefs.values.erase("mp_countdown_reservoir_time");
prefs.values.erase("mp_countdown_turn_bonus");
prefs.values.erase("mp_countdown_action_bonus");
}
std::vector<std::string> v;
v = utils::split(prefs["encountered_units"]);
std::copy(v.begin(), v.end(),
std::inserter(encountered_units_set, encountered_units_set.begin()));
v = utils::split(prefs["encountered_terrains"]);
std::copy(v.begin(), v.end(),
std::inserter(encountered_terrains_set, encountered_terrains_set.begin()));
}
manager::~manager()
{
std::vector<std::string> v;
std::copy(encountered_units_set.begin(), encountered_units_set.end(), std::back_inserter(v));
prefs["encountered_units"] = utils::join(v);
v.clear();
std::copy(encountered_terrains_set.begin(), encountered_terrains_set.end(),
std::back_inserter(v));
prefs["encountered_terrains"] = utils::join(v);
encountered_units_set.clear();
encountered_terrains_set.clear();
try {
scoped_ostream prefs_file = ostream_file(get_prefs_file());
write(*prefs_file, prefs);
} catch(io_exception&) {
std::cerr << "error writing to preferences file '" << get_prefs_file() << "'\n";
}
}
void set(const std::string key, std::string value) {
prefs[key] = value;
}
std::string get(const std::string key) {
return prefs[key];
}
config* get_prefs(){
config* pointer = &prefs;
return pointer;
}
namespace {
bool is_fullscreen = false;
}
bool fullscreen()
{
static bool first_time = true;
if(first_time) {
const string_map::const_iterator fullscreen =
prefs.values.find("fullscreen");
is_fullscreen = fullscreen == prefs.values.end() || fullscreen->second == "true";
}
return is_fullscreen;
}
void _set_fullscreen(bool ison)
{
is_fullscreen = ison;
prefs["fullscreen"] = (ison ? "true" : "false");
}
std::pair<int,int> resolution()
{
const std::string postfix = fullscreen() ? "resolution" : "windowsize";
const string_map::const_iterator x = prefs.values.find('x' + postfix);
const string_map::const_iterator y = prefs.values.find('y' + postfix);
if(x != prefs.values.end() && y != prefs.values.end() &&
x->second.empty() == false && y->second.empty() == false) {
std::pair<int,int> res (maximum(atoi(x->second.c_str()),min_allowed_width),
maximum(atoi(y->second.c_str()),min_allowed_height));
//make sure resolutions are always divisible by 4
//res.first &= ~3;
//res.second &= ~3;
return res;
} else {
return std::pair<int,int>(1024,768);
}
}
bool turbo()
{
if(non_interactive())
return true;
const string_map::const_iterator turbo = prefs.values.find("turbo");
return turbo != prefs.values.end() && turbo->second == "true";
}
void _set_turbo(bool ison)
{
prefs["turbo"] = (ison ? "true" : "false");
}
const std::string& language()
{
return prefs["locale"];
}
void set_language(const std::string& s)
{
prefs["locale"] = s;
}
int music_volume()
{
return lexical_cast_default<int>(prefs["music_volume"], 100);
}
void set_music_volume(int vol)
{
prefs["music_volume"] = lexical_cast_default<std::string>(vol, "100");
sound::set_music_volume(music_volume());
}
int sound_volume()
{
return lexical_cast_default<int>(prefs["sound_volume"], 100);
}
void set_sound_volume(int vol)
{
prefs["sound_volume"] = lexical_cast_default<std::string>(vol, "100");
sound::set_sound_volume(sound_volume());
}
bool adjust_gamma()
{
return prefs["adjust_gamma"] == "yes";
}
void _set_adjust_gamma(bool val)
{
prefs["adjust_gamma"] = val ? "yes" : "no";
}
int gamma()
{
static const int default_value = 100;
const string_map::const_iterator gamma = prefs.values.find("gamma");
if(adjust_gamma() && gamma != prefs.values.end() && gamma->second.empty() == false)
return atoi(gamma->second.c_str());
else
return default_value;
}
void _set_gamma(int gamma)
{
std::stringstream stream;
stream << gamma;
prefs["gamma"] = stream.str();
}
bool grid()
{
const string_map::const_iterator turbo = prefs.values.find("grid");
return turbo != prefs.values.end() && turbo->second == "true";
}
void _set_grid(bool ison)
{
prefs["grid"] = (ison ? "true" : "false");
}
bool lobby_joins()
{
return prefs["lobby_joins"] != "no";
}
void _set_lobby_joins(bool show)
{
if(show)
prefs["lobby_joins"] = "yes";
else
prefs["lobby_joins"] = "no";
}
const std::string& official_network_host()
{
static const std::string host = WESNOTH_DEFAULT_SERVER;
return host;
}
const std::string& network_host()
{
t_string& res = prefs["host"];
if(res.empty())
res = WESNOTH_DEFAULT_SERVER;
return res;
}
void set_network_host(const std::string& host)
{
prefs["host"] = host;
}
const std::string& campaign_server()
{
t_string& res = prefs["campaign_server"];
if(res.empty())
res = "campaigns.wesnoth.org";
return res;
}
void set_campaign_server(const std::string& host)
{
prefs["campaign_server"] = host;
}
const std::string& login()
{
t_string& res = prefs["login"];
if(res.empty()) {
char* const login = getenv("USER");
if(login != NULL) {
res = login;
}
if(res.empty()) {
res = _("player");
}
}
return res;
}
void set_login(const std::string& username)
{
prefs["login"] = username;
}
namespace {
double scroll = 0.2;
}
int scroll_speed()
{
static const int default_value = 50;
int value = 0;
const string_map::const_iterator i = prefs.values.find("scroll");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
if(value < 1 || value > 100) {
value = default_value;
}
scroll = value/100.0;
return value;
}
void set_scroll_speed(int new_speed)
{
std::stringstream stream;
stream << new_speed;
prefs["scroll"] = stream.str();
scroll = new_speed / 100.0;
}
bool turn_bell()
{
return prefs["turn_bell"] == "yes";
}
void set_turn_bell(bool ison)
{
prefs["turn_bell"] = (ison ? "yes" : "no");
}
const std::string& turn_cmd()
{
return prefs["turn_cmd"];
}
void set_turn_cmd(const std::string& cmd)
{
prefs["turn_cmd"] = cmd;
}
bool message_bell()
{
return prefs["message_bell"] != "no";
}
void set_message_bell(bool ison)
{
prefs["message_bell"] = (ison ? "yes" : "no");
}
bool sound_on() {
return prefs["sound"] != "no";
}
bool set_sound(bool ison) {
if(!sound_on() && ison) {
prefs["sound"] = "yes";
if(!music_on()) {
if(!sound::init_sound()) {
prefs["sound"] = "no";
return false;
}
}
} else if(sound_on() && !ison) {
prefs["sound"] = "no";
sound::stop_sound();
if(!music_on())
sound::close_sound();
}
return true;
}
bool music_on() {
return prefs["music"] != "no";
}
bool set_music(bool ison) {
if(!music_on() && ison) {
prefs["music"] = "yes";
if(!sound_on()) {
if(!sound::init_sound()) {
prefs["music"] = "no";
return false;
}
}
else
sound::play_music();
} else if(music_on() && !ison) {
prefs["music"] = "no";
if(!sound_on())
sound::close_sound();
else
sound::stop_music();
}
return true;
}
bool turn_dialog()
{
return prefs["turn_dialog"] == "yes";
}
void set_turn_dialog(bool ison)
{
prefs["turn_dialog"] = (ison ? "yes" : "no");
}
bool show_combat()
{
return prefs["show_combat"] != "no";
}
bool allow_observers()
{
return prefs["allow_observers"] != "no";
}
void set_allow_observers(bool value)
{
prefs["allow_observers"] = value ? "yes" : "no";
}
bool use_map_settings()
{
return prefs["mp_use_map_settings"] != "no";
}
void set_use_map_settings(bool value)
{
prefs["mp_use_map_settings"] = value ? "yes" : "no";
}
bool fog()
{
return prefs["mp_fog"] == "yes";
}
void set_fog(bool value)
{
prefs["mp_fog"] = value ? "yes" : "no";
}
bool shroud()
{
return prefs["mp_shroud"] == "yes";
}
void set_shroud(bool value)
{
prefs["mp_shroud"] = value ? "yes" : "no";
}
int turns()
{
static const int default_value = 50;
int value = 0;
const string_map::const_iterator i = prefs.values.find("mp_turns");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
if(value < 20 || value > 100) {
value = default_value;
}
return value;
}
void set_turns(int value)
{
std::stringstream stream;
stream << value;
prefs["mp_turns"] = stream.str();
}
bool skip_mp_replay()
{
return prefs["skip_mp_replay"] == "yes";
}
void set_skip_mp_replay(bool value)
{
prefs["skip_mp_replay"] = value ? "yes" : "no";
}
bool countdown()
{
return prefs["mp_countdown"] == "yes";
}
void set_countdown(bool value)
{
prefs["mp_countdown"] = value ? "yes" : "no";
}
int countdown_init_time()
{
static const int default_value = 270;
int value = 0;
const std::string& timer_init = prefs["mp_countdown_init_time"];
value = lexical_cast_default<int>(timer_init,default_value);
if(value < 0 || value > 1500) {
value = default_value;
}
return value;
}
void set_countdown_init_time(int value)
{
prefs["mp_countdown_init_time"] = lexical_cast<std::string>(value);
}
int countdown_reservoir_time()
{
static const int default_value = 330;
int value = 0;
const std::string& timer_init = prefs["mp_countdown_reservoir_time"];
value = lexical_cast_default<int>(timer_init,default_value);
if(value < 30 || value > 1500) {
value = default_value;
}
return value;
}
void set_countdown_reservoir_time(int value)
{
prefs["mp_countdown_reservoir_time"] = lexical_cast<std::string>(value);
}
int countdown_turn_bonus()
{
static const int default_value = 40;
int value = 0;
const std::string& timer_bonus = prefs["mp_countdown_turn_bonus"];
value = lexical_cast_default<int>(timer_bonus,default_value);
if(value <= 0 || value > 300) {
value = default_value;
}
return value;
}
void set_countdown_turn_bonus(int value)
{
prefs["mp_countdown_turn_bonus"] =lexical_cast<std::string>(value);
}
int countdown_action_bonus()
{
static const int default_value = 13;
int value = 0;
const std::string& timer_bonus = prefs["mp_countdown_action_bonus"];
value = lexical_cast_default<int>(timer_bonus,default_value);
if(value < 0 || value > 30) {
value = default_value;
}
return value;
}
void set_countdown_action_bonus(int value)
{
prefs["mp_countdown_action_bonus"] =lexical_cast<std::string>(value);
}
int village_gold()
{
static const int default_value = 2;
int value = 0;
const string_map::const_iterator i = prefs.values.find("mp_village_gold");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
if(value < 1 || value > 5) {
value = default_value;
}
return value;
}
void set_village_gold(int value)
{
std::stringstream stream;
stream << value;
prefs["mp_village_gold"] = stream.str();
}
int xp_modifier()
{
static const int default_value = 70;
int value = 0;
const string_map::const_iterator i = prefs.values.find("mp_xp_modifier");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
if(value < 30 || value > 200) {
value = default_value;
}
return value;
}
void set_xp_modifier(int value)
{
std::stringstream stream;
stream << value;
prefs["mp_xp_modifier"] = stream.str();
}
int era()
{
int value = 0;
const string_map::const_iterator i = prefs.values.find("mp_era");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
return value;
}
void set_era(int value)
{
std::stringstream stream;
stream << value;
prefs["mp_era"] = stream.str();
}
int map()
{
int value = 0;
const string_map::const_iterator i = prefs.values.find("mp_map");
if(i != prefs.values.end() && i->second.empty() == false) {
value = atoi(i->second.c_str());
}
return value;
}
void set_map(int value)
{
std::stringstream stream;
stream << value;
prefs["mp_map"] = stream.str();
}
bool show_ai_moves()
{
return prefs["show_ai_moves"] != "no";
}
void set_show_ai_moves(bool value)
{
prefs["show_ai_moves"] = value ? "yes" : "no";
}
void set_show_side_colours(bool value)
{
prefs["show_side_colours"] = value ? "yes" : "no";
}
bool show_side_colours()
{
return prefs["show_side_colours"] != "no";
}
void set_ask_delete_saves(bool value)
{
prefs["ask_delete"] = value ? "yes" : "no";
}
bool ask_delete_saves()
{
return prefs["ask_delete"] != "no";
}
std::string client_type()
{
if(prefs["client_type"] == "ai")
return "ai";
else
return "human";
}
std::string clock_format()
{
if(prefs["clock_format"].size())
return prefs["clock_format"];
else
prefs["clock_format"]="%H:%M:%S";
return "%H:%M:%S";
}
const std::string& theme()
{
if(non_interactive()) {
static const std::string null_theme = "null";
return null_theme;
}
t_string& res = prefs["theme"];
if(res.empty()) {
res = "Default";
}
return res;
}
void set_theme(const std::string& theme)
{
if(theme != "null") {
prefs["theme"] = theme;
}
}
bool use_colour_cursors()
{
return colour_cursors;
}
void _set_colour_cursors(bool value)
{
prefs["colour_cursors"] = value ? "yes" : "no";
colour_cursors = value;
}
bool show_floating_labels()
{
return prefs["floating_labels"] != "no";
}
bool mouse_scroll_enabled()
{
return prefs["mouse_scrolling"] != "no";
}
void enable_mouse_scroll(bool value)
{
prefs["mouse_scrolling"] = value ? "yes" : "no";
}
void set_show_floating_labels(bool value)
{
prefs["floating_labels"] = value ? "yes" : "no";
}
bool message_private()
{
return message_private_on;
}
void set_message_private(bool value)
{
message_private_on = value;
}
bool show_tip_of_day()
{
return prefs["tip_of_day"] != "no";
}
void set_show_tip_of_day(bool value)
{
prefs["tip_of_day"] = value ? "yes" : "no";
}
bool show_haloes()
{
return haloes;
}
void set_show_haloes(bool value)
{
haloes = value;
prefs["show_haloes"] = value ? "yes" : "no";
}
bool flip_time()
{
return prefs["flip_time"] == "yes";
}
void set_flip_time(bool value)
{
prefs["flip_time"] = value ? "yes" : "no";
}
bool show_fps()
{
return fps;
}
void set_show_fps(bool value)
{
fps = value;
}
bool upload_log()
{
return prefs["upload_log"] == "yes";
}
void set_upload_log(bool value)
{
prefs["upload_log"] = value ? "yes" : "no";
}
const std::string &upload_id()
{
// We create a unique id for each person, *when asked for* to increase
// randomness.
if (prefs["upload_id"] == "") {
srand(time(NULL));
prefs["upload_id"]
= lexical_cast<std::string>(rand())
+ lexical_cast<std::string>(SDL_GetTicks());
}
return prefs["upload_id"];
}
bool compress_saves()
{
return prefs["compress_saves"] != "no";
}
bool chat_timestamp()
{
return prefs["chat_timestamp"] == "yes";
}
void set_chat_timestamp(bool value)
{
prefs["chat_timestamp"] = value ? "yes" : "no";
}
int chat_lines()
{
// defaults to 6 chat log lines displayed
static const int default_value = 6;
const string_map::const_iterator lines = prefs.values.find("chat_lines");
if(lines != prefs.values.end() && lines->second.empty() == false)
return atoi(lines->second.c_str());
else
return default_value;
}
void set_chat_lines(int lines)
{
std::stringstream stream;
stream << lines;
prefs["chat_lines"] = stream.str();
}
std::set<std::string> &encountered_units() {
return encountered_units_set;
}
std::set<std::string> &encountered_terrains() {
return encountered_terrains_set;
}
CACHE_SAVES_METHOD cache_saves()
{
if(prefs["cache_saves"] == "always") {
return CACHE_SAVES_ALWAYS;
} else if(prefs["cache_saves"] == "never") {
return CACHE_SAVES_NEVER;
} else {
return CACHE_SAVES_ASK;
}
}
void set_cache_saves(CACHE_SAVES_METHOD method)
{
switch(method) {
case CACHE_SAVES_ALWAYS:
prefs["cache_saves"] = "always";
break;
case CACHE_SAVES_NEVER:
prefs["cache_saves"] = "never";
break;
case CACHE_SAVES_ASK:
prefs["cache_saves"] = "ask";
break;
}
}
bool compare_resolutions(const std::pair<int,int>& lhs, const std::pair<int,int>& rhs)
{
return lhs.first*lhs.second < rhs.first*rhs.second;
}
bool green_confirm()
{
std::string confirmation = prefs["confirm_end_turn"];
if (confirmation == "green" || confirmation == "yes")
return true;
return false;
}
bool yellow_confirm()
{
return prefs["confirm_end_turn"] == "yellow";
}
bool confirm_no_moves()
{
//This is very non-intrusive so it is on by default
const std::string confirmation = prefs["confirm_end_turn"];
return confirmation == "no_moves" || confirmation.empty();
}
void load_hotkeys() {
hotkey::load_hotkeys(prefs);
}
void save_hotkeys() {
hotkey::save_hotkeys(prefs);
}
void encounter_recruitable_units(std::vector<team>& teams){
for (std::vector<team>::iterator help_team_it = teams.begin();
help_team_it != teams.end(); help_team_it++) {
help_team_it->log_recruitable();
std::copy(help_team_it->recruits().begin(), help_team_it->recruits().end(),
std::inserter(encountered_units_set, encountered_units_set.begin()));
}
}
void encounter_start_units(unit_map& units){
for (unit_map::const_iterator help_unit_it = units.begin();
help_unit_it != units.end(); help_unit_it++) {
const std::string name = help_unit_it->second.id();
encountered_units_set.insert(name);
}
}
void encounter_recallable_units(game_state& gamestate){
for(std::map<std::string, player_info>::iterator pi = gamestate.players.begin(); pi!=gamestate.players.end(); ++pi) {
for(std::vector<unit>::iterator help_recall_it = pi->second.available_units.begin(); help_recall_it != pi->second.available_units.end(); help_recall_it++) {
encountered_units_set.insert(help_recall_it->id());
}
}
}
void encounter_map_terrain(gamemap& map){
for (int map_x = 0; map_x < map.x(); map_x++) {
for (int map_y = 0; map_y < map.y(); map_y++) {
const gamemap::TERRAIN t = map.get_terrain(gamemap::location(map_x, map_y));
std::string s;
s += t;
preferences::encountered_terrains().insert(s);
}
}
}
}