Patch from jacobhs to escape save games filenames...

...to allow special characters on them
This commit is contained in:
uid67456 2004-01-29 02:00:32 +00:00
parent f57bb19eb7
commit 855aaf0946
6 changed files with 91 additions and 5 deletions

View file

@ -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

View file

@ -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);

View file

@ -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());
}

View file

@ -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);

View file

@ -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,

View file

@ -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())