1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/**
* C++ Implementation: textstyle
*
* Description:
*
* Author: Lorenzo Bettini <http://www.lorenzobettini.it>, (C) 2005
* Copyright: See COPYING file that comes with this distribution
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "textstyle.h"
#include <sstream>
using namespace std;
namespace srchilite {
static SubstitutionMapping substitutionmapping;
TextStyle::TextStyle(const string &s,const char **vars) : repr((s.size() ? s : TEXT_VAR_TEXT)),
invalid(true)
{
ostringstream exp_buff;
exp_buff << "\\$(style|text";
if (vars) {
int i = 0;
while (vars[i]) {
exp_buff << "|" << vars[i];
++i;
}
}
exp_buff << ")";
var_exp = boost::regex(exp_buff.str());
}
TextStyle::~TextStyle()
{
}
/**
* The parts vector contains the string repr split in parts: those that
* constant parts and those that represent $text and $style variables.
* For instance, if repr == "<span class=\"$style\">$text</span>", then we
* have:
*
* - parts[0] == "<span class=\""
* - parts[1] == ""
* - parts[2] == "\">"
* - parts[3] == ""
* - parts[4] == "</span>"
*
* Then style_substitutions contains the index(es) of parts corresponding to
* $style variable occurrences that will be substituted with values
* and text_substitutions is the same but for $text occurrences. Thus, in this
* case:
*
* - style_substitutions[0] = 1
* - text_substitutions[0] = 3
*/
void
TextStyle::build_vectors()
{
parts.clear();
substitutions.clear();
boost::sregex_iterator i1(repr.begin(), repr.end(), var_exp);
boost::sregex_iterator i2;
string suffix;
if (i1 == i2)
return ;
int index = -1;
for (boost::sregex_iterator it = i1; it != i2; ++it) {
string prefix = it->prefix();
if (prefix.size()) {
parts.push_back(prefix);
++index;
}
++index;
string matched = string((*it)[0].first, (*it)[0].second);
substitutions[matched].push_back(index);
suffix = it->suffix();
parts.push_back(""); // this will be set during "output"
// with a value for $text or $style
}
if (suffix.size())
parts.push_back(suffix);
}
/**
* First substitute in the vector parts the values for $text and
* $style and return a string with the substituted values.
*
* @param text
* @param style
* @return
*/
string
TextStyle::output(const string &text, const string &style)
{
substitutionmapping["$text"] = text;
substitutionmapping["$style"] = style;
return output(substitutionmapping);
}
/**
* for each i substitutes: subst_map[i].first occurrence with subst_map[i].second
*/
std::string TextStyle::output(SubstitutionMapping &subst_map)
{
if (invalid) {
build_vectors();
invalid = false;
}
SubstitutionIndexes::const_iterator subIt;
IndexVector::const_iterator indexIt;
for (subIt = substitutions.begin(); subIt != substitutions.end(); ++subIt) {
for (indexIt = subIt->second.begin(); indexIt != subIt->second.end(); ++indexIt) {
parts[*indexIt] = subst_map[subIt->first];
}
}
string ret;
for (StringVector::const_iterator it = parts.begin(); it != parts.end(); ++it)
ret += *it;
return ret;
}
string
TextStyle::subst_style(const string &style)
{
return output(TEXT_VAR_TEXT, style); // leave $text untouched
}
TextStyle
TextStyle::compose(const TextStyle &inner)
{
return TextStyle(output(inner.toString()));
}
void
TextStyle::update(const string &inner)
{
repr = output(inner);
invalid = true;
}
void
TextStyle::update(const string &text, const string &style)
{
repr = output(text, style);
invalid = true;
}
void
TextStyle::update(const TextStyle &inner)
{
update(inner.toString());
}
bool
TextStyle::containsStyleVar() const
{
boost::regex style_exp(STYLE_VAR);
return boost::regex_search(repr, style_exp);
}
bool
TextStyle::empty() const
{
return repr == STYLE_VAR_TEXT || repr == TEXT_VAR_TEXT;
}
}
|