From 3800d44b7952e7ae1f05b711ad46268dde11821d Mon Sep 17 00:00:00 2001 From: haranp Date: Mon, 13 Oct 2008 11:16:17 +0000 Subject: Fix 2162827: tag length calculation was incorrect. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7230 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/format.cc | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'crawl-ref/source/format.cc') diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc index e4280e5038..9cd282e058 100644 --- a/crawl-ref/source/format.cc +++ b/crawl-ref/source/format.cc @@ -577,3 +577,96 @@ int count_linebreaks(const formatted_string& fs) } return count; } + +// Return the actual (string) offset of character #loc to be printed, +// i.e. ignoring tags. So for instance, if s == "ab", then +// _find_string_location(s, 2) == 6. +int _find_string_location(const std::string& s, int loc) +{ + int real_offset = 0; + bool in_tag = false; + int last_taglen = 0; + int offset = 0; + for (std::string::const_iterator ci = s.begin(); + ci != s.end() && real_offset < loc; + ++ci, ++offset) + { + if (in_tag) + { + if (*ci == '<' && last_taglen == 1) + { + ++real_offset; + in_tag = false; + } + else if (*ci == '>') + { + in_tag = false; + } + else + { + ++last_taglen; + } + } + else if (*ci == '<') + { + in_tag = true; + last_taglen = 1; + } + else + { + ++real_offset; + } + } + return (offset); +} + +// Return the substring of s from character start to character end, +// where tags count as length 0. +std::string tagged_string_substr(const std::string& s, int start, int end) +{ + return (s.substr(_find_string_location(s, start), + _find_string_location(s, end))); +} + +int tagged_string_printable_length(const std::string& s) +{ + int len = 0; + bool in_tag = false; + int last_taglen = 0; + for (std::string::const_iterator ci = s.begin(); ci != s.end(); ++ci) + { + if (in_tag) + { + if (*ci == '<' && last_taglen == 1) // "<<" sequence + { + in_tag = false; // this is an escape for '<' + ++len; // len wasn't incremented before + } + else if (*ci == '>') // tag close, still nothing printed + { + in_tag = false; + } + else // tag continues + { + ++last_taglen; + } + } + else if (*ci == '<') // tag starts + { + in_tag = true; + last_taglen = 1; + } + else // normal, printable character + { + ++len; + } + } + return (len); +} + + +// Count the length of the tags in the string. +int tagged_string_tag_length(const std::string& s) +{ + return s.size() - tagged_string_printable_length(s); +} -- cgit v1.2.3-54-g00ecf