Patch from jacobhs to escape save games filenames...
...to allow special characters on them
This commit is contained in:
parent
f57bb19eb7
commit
855aaf0946
6 changed files with 91 additions and 5 deletions
|
@ -800,6 +800,46 @@ std::vector<std::string> config::split(const std::string& val, char c, bool remo
|
|||
|
||||
return res;
|
||||
}
|
||||
//identical to split(), except it does not split when it otherwise
|
||||
//would if the previous character was identical to the parameter 'quote'.
|
||||
//i.e. it does not split quoted commas.
|
||||
//this method was added to make it possible to quote user input,
|
||||
//particularly so commas in user input will not cause visual problems in menus.
|
||||
//why not change split()? that would change the methods post condition.
|
||||
std::vector<std::string> config::quoted_split(const std::string& val, char c, bool remove_empty, char quote)
|
||||
{
|
||||
std::vector<std::string> res;
|
||||
|
||||
std::string::const_iterator i1 = val.begin();
|
||||
std::string::const_iterator i2 = val.begin();
|
||||
|
||||
while(i2 != val.end()) {
|
||||
if(*i2 == quote) {
|
||||
// ignore quoted character
|
||||
++i2;
|
||||
if(i2 != val.end()) ++i2;
|
||||
} else if(*i2 == c) {
|
||||
std::string new_val(i1,i2);
|
||||
strip(new_val);
|
||||
if(!remove_empty || !new_val.empty())
|
||||
res.push_back(new_val);
|
||||
++i2;
|
||||
while(i2 != val.end() && *i2 == ' ')
|
||||
++i2;
|
||||
|
||||
i1 = i2;
|
||||
} else {
|
||||
++i2;
|
||||
}
|
||||
}
|
||||
|
||||
std::string new_val(i1,i2);
|
||||
strip(new_val);
|
||||
if(!remove_empty || !new_val.empty())
|
||||
res.push_back(new_val);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace {
|
||||
//make sure we regard '\r' and '\n' as a space, since Mac, Unix, and DOS
|
||||
|
@ -807,6 +847,38 @@ namespace {
|
|||
bool notspace(char c) { return !portable_isspace(c); }
|
||||
}
|
||||
|
||||
//prepend all special characters with a backslash
|
||||
//special characters are:
|
||||
//#@{}+-,\*
|
||||
std::string& config::escape(std::string& str)
|
||||
{
|
||||
if(!str.empty()) {
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
do {
|
||||
pos=str.find_first_of("#@{}+-,\\*",pos);
|
||||
if(pos != std::string::npos) {
|
||||
str.insert(pos,1,'\\');
|
||||
pos += 2;
|
||||
}
|
||||
} while(pos < str.size() && pos != std::string::npos);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
// remove all escape characters (backslash)
|
||||
std::string& config::unescape(std::string& str)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
|
||||
do {
|
||||
pos = str.find('\\',pos);
|
||||
if(pos != std::string::npos) {
|
||||
str.erase(pos,1);
|
||||
pos++;
|
||||
}
|
||||
} while(pos < str.size() && pos != std::string::npos);
|
||||
return str;
|
||||
}
|
||||
std::string& config::strip(std::string& str)
|
||||
{
|
||||
//if all the string contains is whitespace, then the whitespace may
|
||||
|
|
|
@ -106,7 +106,7 @@ struct config
|
|||
|
||||
const child_list& get_children(const std::string& key) const;
|
||||
const child_map& all_children() const;
|
||||
|
||||
|
||||
config* child(const std::string& key);
|
||||
const config* child(const std::string& key) const;
|
||||
config& add_child(const std::string& key);
|
||||
|
@ -123,6 +123,10 @@ struct config
|
|||
config* remove_child(const std::string& key, size_t index);
|
||||
|
||||
static std::vector<std::string> split(const std::string& val, char c=',', bool remove_empty=true);
|
||||
static std::vector<std::string> quoted_split(const std::string& val, char c=',',
|
||||
bool remove_empty=true, char quote='\\');
|
||||
static std::string& escape(std::string& str);
|
||||
static std::string& unescape(std::string& str);
|
||||
static std::string& strip(std::string& str);
|
||||
static bool has_value(const std::string& values, const std::string& val);
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ std::string load_game_dialog(display& disp, bool* show_replay)
|
|||
time_buf[0] = 0;
|
||||
|
||||
std::stringstream str;
|
||||
str << name << "," << time_buf;
|
||||
// escape all special characters in filenames
|
||||
str << config::escape(name) << "," << time_buf;
|
||||
items.push_back(str.str());
|
||||
}
|
||||
|
||||
|
|
11
src/font.cpp
11
src/font.cpp
|
@ -249,7 +249,11 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|||
SDL_Color col = colour;
|
||||
int sz = size;
|
||||
if(use_markup == USE_MARKUP) {
|
||||
if(*i1 == '#') {
|
||||
if(*i1 == '\\') {
|
||||
// this must either be a quoted special character or a
|
||||
// quoted backslash - either way, we remove the leading backslash
|
||||
++i1;
|
||||
} else if(*i1 == '#') {
|
||||
col = BAD_COLOUR;
|
||||
++i1;
|
||||
} else if(*i1 == '@') {
|
||||
|
@ -276,7 +280,10 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|||
}
|
||||
|
||||
if(i1 != i2) {
|
||||
const std::string new_string(i1,i2);
|
||||
std::string new_string(i1,i2);
|
||||
|
||||
config::unescape(new_string);
|
||||
|
||||
const SDL_Rect rect =
|
||||
draw_text_line(gui,area,sz,col,new_string,x,y,bg,
|
||||
use_tooltips);
|
||||
|
|
|
@ -51,6 +51,8 @@ enum MARKUP { USE_MARKUP, NO_MARKUP };
|
|||
// - any line beginning in - will be displayed with size decreased by 2
|
||||
// - any line beginning with 0x0n will be displayed in the colour of side n
|
||||
//
|
||||
//the above special characters can be quoted using a C-style backslash.
|
||||
//
|
||||
//a bounding rectangle of the text is returned. If gui is NULL, then the
|
||||
//text will not be drawn, and a bounding rectangle only will be returned.
|
||||
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
||||
|
|
|
@ -28,7 +28,7 @@ menu::menu(display& disp, const std::vector<std::string>& items,
|
|||
{
|
||||
for(std::vector<std::string>::const_iterator item = items.begin();
|
||||
item != items.end(); ++item) {
|
||||
items_.push_back(config::split(*item,',',false));
|
||||
items_.push_back(config::quoted_split(*item,',',false));
|
||||
|
||||
//make sure there is always at least one item
|
||||
if(items_.back().empty())
|
||||
|
|
Loading…
Add table
Reference in a new issue