2 * @file SubstitutionFiltersList.cpp
4 * @brief Implementation for SubstitutionFiltersList class.
8 #include "SubstitutionFiltersList.h"
9 #include "SubstitutionList.h"
12 #include <Poco/Exception.h>
13 #include "OptionsMgr.h"
14 #include "OptionsDef.h"
15 #include "UnicodeString.h"
17 /** @brief Registry key for saving Substitution filters. */
18 static const TCHAR SubstitutionFiltersRegPath[] = _T("SubstitutionFilters");
21 * @brief Default constructor.
23 SubstitutionFiltersList::SubstitutionFiltersList()
24 : m_pOptionsMgr(nullptr)
29 * @brief Destructor, empties the list.
31 SubstitutionFiltersList::~SubstitutionFiltersList()
36 * @brief Add new filter to the list.
37 * @param [in] filter Filter string to add.
38 * @param [in] enabled Is filter enabled?
40 void SubstitutionFiltersList::Add(const String& filter0, const String& filter1,
41 bool useRegExp, bool caseSensitive, bool matchWholeWordOnly, bool enabled)
43 SubstitutionFilter item;
44 item.useRegExp = useRegExp;
45 item.caseSensitive = caseSensitive;
46 item.matchWholeWordOnly = matchWholeWordOnly;
47 item.pattern = filter0;
48 item.replacement = filter1;
49 item.enabled = enabled;
50 m_items.emplace_back(item);
54 * @brief Return filter from given index.
55 * @param [in] ind Index of filter.
56 * @return Filter item from the index. If the index is beyond table limit,
57 * return the last item in the list.
59 const SubstitutionFilter& SubstitutionFiltersList::GetAt(size_t ind) const
61 if (ind < m_items.size())
64 return m_items.back();
68 * @brief Clone filter list from another list.
69 * This function clones filter list from another list. Current items in the
70 * list are removed and new items added from the given list.
71 * @param [in] list List to clone.
73 void SubstitutionFiltersList::CloneFrom(const SubstitutionFiltersList *list)
76 size_t count = list->GetCount();
77 m_enabled = list->m_enabled;
78 for (size_t i = 0; i < count; i++)
80 const SubstitutionFilter &item = list->GetAt(i);
81 Add(item.pattern, item.replacement, item.useRegExp,
82 item.caseSensitive, item.matchWholeWordOnly, item.enabled);
87 * @brief Compare filter lists.
88 * @param [in] list List to compare.
89 * @return true if lists are identical, false otherwise.
91 bool SubstitutionFiltersList::Compare(const SubstitutionFiltersList *list) const
93 if (list->GetCount() != GetCount())
95 if (list->GetEnabled() != GetEnabled())
98 for (size_t i = 0; i < GetCount(); i++)
100 const SubstitutionFilter &item1 = list->GetAt(i);
101 const SubstitutionFilter &item2 = GetAt(i);
105 item1.enabled != item2.enabled
106 || item1.useRegExp != item2.useRegExp
107 || item1.caseSensitive != item2.caseSensitive
108 || item1.matchWholeWordOnly != item2.matchWholeWordOnly
109 || item1.pattern != item2.pattern
110 || item1.replacement != item2.replacement
118 * @brief Read filter list from the options system.
119 * @param [in] pOptionsMgr Pointer to options system.
121 void SubstitutionFiltersList::Initialize(COptionsMgr *pOptionsMgr)
123 assert(pOptionsMgr != nullptr);
124 String valuename(SubstitutionFiltersRegPath);
126 m_pOptionsMgr = pOptionsMgr;
128 m_enabled = m_pOptionsMgr->GetBool(OPT_SUBSTITUTION_FILTERS_ENABLED);
130 size_t count = m_items.size();
131 valuename += _T("/Values");
132 m_pOptionsMgr->InitOption(valuename, static_cast<int>(count));
133 count = m_pOptionsMgr->GetInt(valuename);
135 for (unsigned i = 0; i < count; i++)
137 String nameEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, i);
138 m_pOptionsMgr->InitOption(nameEnabled, true);
139 bool enabled = m_pOptionsMgr->GetBool(nameEnabled);
141 String nameUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, i);
142 m_pOptionsMgr->InitOption(nameUseRegExp, false);
143 bool useRegExp = m_pOptionsMgr->GetBool(nameUseRegExp);
145 String nameCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, i);
146 m_pOptionsMgr->InitOption(nameCaseSensitive, false);
147 bool caseSensitive = m_pOptionsMgr->GetBool(nameCaseSensitive);
149 String nameMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, i);
150 m_pOptionsMgr->InitOption(nameMatchWholeWordOnly, false);
151 bool matchWholeWordOnly = m_pOptionsMgr->GetBool(nameMatchWholeWordOnly);
153 String name0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, i);
154 m_pOptionsMgr->InitOption(name0, _T(""));
155 String pattern = m_pOptionsMgr->GetString(name0);
157 String name1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, i);
158 m_pOptionsMgr->InitOption(name1, _T(""));
159 String replacement = m_pOptionsMgr->GetString(name1);
161 Add(pattern, replacement, useRegExp, caseSensitive, matchWholeWordOnly, enabled);
166 * @brief Save Substitution Filters to options system.
168 void SubstitutionFiltersList::SaveFilters()
170 assert(m_pOptionsMgr != nullptr);
171 String valuename(SubstitutionFiltersRegPath);
173 m_pOptionsMgr->SaveOption(OPT_SUBSTITUTION_FILTERS_ENABLED, m_enabled);
175 size_t count = m_items.size();
176 valuename += _T("/Values");
177 m_pOptionsMgr->SaveOption(valuename, static_cast<int>(count));
179 for (size_t i = 0; i < count; i++)
181 const SubstitutionFilter& item = m_items[i];
183 String nameEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, i);
184 m_pOptionsMgr->InitOption(nameEnabled, true);
185 m_pOptionsMgr->SaveOption(nameEnabled, item.enabled);
187 String nameUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, i);
188 m_pOptionsMgr->InitOption(nameUseRegExp, false);
189 m_pOptionsMgr->SaveOption(nameUseRegExp, item.useRegExp);
191 String nameCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, i);
192 m_pOptionsMgr->InitOption(nameCaseSensitive, false);
193 m_pOptionsMgr->SaveOption(nameCaseSensitive, item.caseSensitive);
195 String nameMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, i);
196 m_pOptionsMgr->InitOption(nameMatchWholeWordOnly, false);
197 m_pOptionsMgr->SaveOption(nameMatchWholeWordOnly, item.matchWholeWordOnly);
199 String name0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, i);
200 m_pOptionsMgr->InitOption(name0, _T(""));
201 m_pOptionsMgr->SaveOption(name0, item.pattern);
203 String name1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, i);
204 m_pOptionsMgr->InitOption(name1, _T(""));
205 m_pOptionsMgr->SaveOption(name1, item.replacement);
208 // Remove options we don't need anymore
209 // We could have earlier 10 pcs but now we only need 5
210 String filterEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, count);
211 int retvalEnabled = m_pOptionsMgr->RemoveOption(filterEnabled);
213 String filterUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, count);
214 int retvalUseRegExp = m_pOptionsMgr->RemoveOption(filterUseRegExp);
216 String filterCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, count);
217 int retvalCaseSensitive = m_pOptionsMgr->RemoveOption(filterCaseSensitive);
219 String filterMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, count);
220 int retvalMatchWholeWordOnly = m_pOptionsMgr->RemoveOption(filterMatchWholeWordOnly);
222 String filter0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, count);
223 int retval0 = m_pOptionsMgr->RemoveOption(filter0);
225 String filter1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, count);
226 int retval1 = m_pOptionsMgr->RemoveOption(filter1);
228 while (retvalEnabled == COption::OPT_OK || retvalUseRegExp == COption::OPT_OK ||
229 retvalCaseSensitive == COption::OPT_OK || retvalMatchWholeWordOnly == COption::OPT_OK ||
230 retval0 == COption::OPT_OK || retval1 == COption::OPT_OK)
233 filterEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, count);
234 retvalEnabled = m_pOptionsMgr->RemoveOption(filterEnabled);
235 filterUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, count);
236 retvalUseRegExp = m_pOptionsMgr->RemoveOption(filterUseRegExp);
237 filterCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, count);
238 retvalCaseSensitive = m_pOptionsMgr->RemoveOption(filterCaseSensitive);
239 filterMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, count);
240 retvalMatchWholeWordOnly = m_pOptionsMgr->RemoveOption(filterMatchWholeWordOnly);
241 filter0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, count);
242 retval0 = m_pOptionsMgr->RemoveOption(filter0);
243 filter1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, count);
244 retval1 = m_pOptionsMgr->RemoveOption(filter1);
248 std::shared_ptr<SubstitutionList> SubstitutionFiltersList::MakeSubstitutionList(bool throwIfInvalid)
251 std::shared_ptr<SubstitutionList> plist(new SubstitutionList);
252 for (auto& item : m_items)
261 ucr::toUTF8(item.pattern),
262 ucr::toUTF8(item.replacement),
263 item.caseSensitive ? 0 : Poco::RegularExpression::RE_CASELESS);
268 ucr::toUTF8(item.pattern),
269 ucr::toUTF8(item.replacement),
270 item.caseSensitive, item.matchWholeWordOnly);
273 catch (const Poco::RegularExpressionException& e)
279 _snprintf_s(msg, _TRUNCATE, "#%d: %s", i + 1, e.message().c_str());
280 throw Poco::RegularExpressionException(msg, e.code());