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_t SubstitutionFiltersRegPath[] = _T("SubstitutionFilters");
21 * @brief Default constructor.
23 SubstitutionFiltersList::SubstitutionFiltersList()
24 : m_pOptionsMgr(nullptr)
29 * @brief Destructor, empties the list.
31 SubstitutionFiltersList::~SubstitutionFiltersList() = default;
34 * @brief Add new filter to the list.
35 * @param [in] filter Filter string to add.
36 * @param [in] enabled Is filter enabled?
38 void SubstitutionFiltersList::Add(const String& filter0, const String& filter1,
39 bool useRegExp, bool caseSensitive, bool matchWholeWordOnly, bool enabled)
41 SubstitutionFilter item;
42 item.useRegExp = useRegExp;
43 item.caseSensitive = caseSensitive;
44 item.matchWholeWordOnly = matchWholeWordOnly;
45 item.pattern = filter0;
46 item.replacement = filter1;
47 item.enabled = enabled;
48 m_items.emplace_back(item);
52 * @brief Return filter from given index.
53 * @param [in] ind Index of filter.
54 * @return Filter item from the index. If the index is beyond table limit,
55 * return the last item in the list.
57 const SubstitutionFilter& SubstitutionFiltersList::GetAt(size_t ind) const
59 if (ind < m_items.size())
62 return m_items.back();
66 * @brief Clone filter list from another list.
67 * This function clones filter list from another list. Current items in the
68 * list are removed and new items added from the given list.
69 * @param [in] list List to clone.
71 void SubstitutionFiltersList::CloneFrom(const SubstitutionFiltersList *list)
74 size_t count = list->GetCount();
75 m_enabled = list->m_enabled;
76 for (size_t i = 0; i < count; i++)
78 const SubstitutionFilter &item = list->GetAt(i);
79 Add(item.pattern, item.replacement, item.useRegExp,
80 item.caseSensitive, item.matchWholeWordOnly, item.enabled);
85 * @brief Compare filter lists.
86 * @param [in] list List to compare.
87 * @return true if lists are identical, false otherwise.
89 bool SubstitutionFiltersList::Compare(const SubstitutionFiltersList *list) const
91 if (list->GetCount() != GetCount())
93 if (list->GetEnabled() != GetEnabled())
96 for (size_t i = 0; i < GetCount(); i++)
98 const SubstitutionFilter &item1 = list->GetAt(i);
99 const SubstitutionFilter &item2 = GetAt(i);
103 item1.enabled != item2.enabled
104 || item1.useRegExp != item2.useRegExp
105 || item1.caseSensitive != item2.caseSensitive
106 || item1.matchWholeWordOnly != item2.matchWholeWordOnly
107 || item1.pattern != item2.pattern
108 || item1.replacement != item2.replacement
116 * @brief Read filter list from the options system.
117 * @param [in] pOptionsMgr Pointer to options system.
119 void SubstitutionFiltersList::Initialize(COptionsMgr *pOptionsMgr)
121 assert(pOptionsMgr != nullptr);
122 String valuename(SubstitutionFiltersRegPath);
124 m_pOptionsMgr = pOptionsMgr;
126 m_enabled = m_pOptionsMgr->GetBool(OPT_SUBSTITUTION_FILTERS_ENABLED);
130 valuename += _T("/Values");
131 m_pOptionsMgr->InitOption(valuename, 0);
132 size_t count = m_pOptionsMgr->GetInt(valuename);
134 for (unsigned i = 0; i < count; i++)
136 String nameEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, i);
137 m_pOptionsMgr->InitOption(nameEnabled, true);
138 bool enabled = m_pOptionsMgr->GetBool(nameEnabled);
140 String nameUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, i);
141 m_pOptionsMgr->InitOption(nameUseRegExp, false);
142 bool useRegExp = m_pOptionsMgr->GetBool(nameUseRegExp);
144 String nameCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, i);
145 m_pOptionsMgr->InitOption(nameCaseSensitive, false);
146 bool caseSensitive = m_pOptionsMgr->GetBool(nameCaseSensitive);
148 String nameMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, i);
149 m_pOptionsMgr->InitOption(nameMatchWholeWordOnly, false);
150 bool matchWholeWordOnly = m_pOptionsMgr->GetBool(nameMatchWholeWordOnly);
152 String name0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, i);
153 m_pOptionsMgr->InitOption(name0, _T(""));
154 String pattern = m_pOptionsMgr->GetString(name0);
156 String name1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, i);
157 m_pOptionsMgr->InitOption(name1, _T(""));
158 String replacement = m_pOptionsMgr->GetString(name1);
160 Add(pattern, replacement, useRegExp, caseSensitive, matchWholeWordOnly, enabled);
165 * @brief Save Substitution Filters to options system.
167 void SubstitutionFiltersList::SaveFilters()
169 assert(m_pOptionsMgr != nullptr);
170 String valuename(SubstitutionFiltersRegPath);
172 m_pOptionsMgr->SaveOption(OPT_SUBSTITUTION_FILTERS_ENABLED, m_enabled);
174 size_t count = m_items.size();
175 valuename += _T("/Values");
176 m_pOptionsMgr->SaveOption(valuename, static_cast<int>(count));
178 for (size_t i = 0; i < count; i++)
180 const SubstitutionFilter& item = m_items[i];
182 String nameEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, i);
183 m_pOptionsMgr->InitOption(nameEnabled, true);
184 m_pOptionsMgr->SaveOption(nameEnabled, item.enabled);
186 String nameUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, i);
187 m_pOptionsMgr->InitOption(nameUseRegExp, false);
188 m_pOptionsMgr->SaveOption(nameUseRegExp, item.useRegExp);
190 String nameCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, i);
191 m_pOptionsMgr->InitOption(nameCaseSensitive, false);
192 m_pOptionsMgr->SaveOption(nameCaseSensitive, item.caseSensitive);
194 String nameMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, i);
195 m_pOptionsMgr->InitOption(nameMatchWholeWordOnly, false);
196 m_pOptionsMgr->SaveOption(nameMatchWholeWordOnly, item.matchWholeWordOnly);
198 String name0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, i);
199 m_pOptionsMgr->InitOption(name0, _T(""));
200 m_pOptionsMgr->SaveOption(name0, item.pattern);
202 String name1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, i);
203 m_pOptionsMgr->InitOption(name1, _T(""));
204 m_pOptionsMgr->SaveOption(name1, item.replacement);
207 // Remove options we don't need anymore
208 // We could have earlier 10 pcs but now we only need 5
209 String filterEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, count);
210 int retvalEnabled = m_pOptionsMgr->RemoveOption(filterEnabled);
212 String filterUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, count);
213 int retvalUseRegExp = m_pOptionsMgr->RemoveOption(filterUseRegExp);
215 String filterCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, count);
216 int retvalCaseSensitive = m_pOptionsMgr->RemoveOption(filterCaseSensitive);
218 String filterMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, count);
219 int retvalMatchWholeWordOnly = m_pOptionsMgr->RemoveOption(filterMatchWholeWordOnly);
221 String filter0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, count);
222 int retval0 = m_pOptionsMgr->RemoveOption(filter0);
224 String filter1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, count);
225 int retval1 = m_pOptionsMgr->RemoveOption(filter1);
227 while (retvalEnabled == COption::OPT_OK || retvalUseRegExp == COption::OPT_OK ||
228 retvalCaseSensitive == COption::OPT_OK || retvalMatchWholeWordOnly == COption::OPT_OK ||
229 retval0 == COption::OPT_OK || retval1 == COption::OPT_OK)
232 filterEnabled = strutils::format(_T("%s/Enabled%02u"), SubstitutionFiltersRegPath, count);
233 retvalEnabled = m_pOptionsMgr->RemoveOption(filterEnabled);
234 filterUseRegExp = strutils::format(_T("%s/UseRegExp%02u"), SubstitutionFiltersRegPath, count);
235 retvalUseRegExp = m_pOptionsMgr->RemoveOption(filterUseRegExp);
236 filterCaseSensitive = strutils::format(_T("%s/CaseSensitive%02u"), SubstitutionFiltersRegPath, count);
237 retvalCaseSensitive = m_pOptionsMgr->RemoveOption(filterCaseSensitive);
238 filterMatchWholeWordOnly = strutils::format(_T("%s/MatchWholeWordOnly%02u"), SubstitutionFiltersRegPath, count);
239 retvalMatchWholeWordOnly = m_pOptionsMgr->RemoveOption(filterMatchWholeWordOnly);
240 filter0 = strutils::format(_T("%s/Pattern%02u"), SubstitutionFiltersRegPath, count);
241 retval0 = m_pOptionsMgr->RemoveOption(filter0);
242 filter1 = strutils::format(_T("%s/Replacement%02u"), SubstitutionFiltersRegPath, count);
243 retval1 = m_pOptionsMgr->RemoveOption(filter1);
247 std::shared_ptr<SubstitutionList> SubstitutionFiltersList::MakeSubstitutionList(bool throwIfInvalid)
250 std::shared_ptr<SubstitutionList> plist(new SubstitutionList);
251 for (auto& item : m_items)
253 if (item.enabled && !item.pattern.empty())
260 ucr::toUTF8(item.pattern),
261 ucr::toUTF8(item.replacement),
262 (item.caseSensitive ? 0 : Poco::RegularExpression::RE_CASELESS) |
263 Poco::RegularExpression::RE_MULTILINE);
268 ucr::toUTF8(item.pattern),
269 ucr::toUTF8(item.replacement),
270 item.caseSensitive, item.matchWholeWordOnly);
273 catch (const Poco::RegularExpressionException& e)
278 const String msg = strutils::format(_T("#%d: %s"), i + 1, e.message().c_str());
279 throw Poco::RegularExpressionException(ucr::toUTF8(msg).c_str(), e.code());