summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-04-29 14:20:42 +0200
committerMaxime Coste <frrrwww@gmail.com>2013-04-29 14:20:42 +0200
commit11bc24f992244b01859ce1dc532d983d96fbb328 (patch)
tree8c81191ee40ee8f6ba82c407fce59c2384167d67 /src
parentba562367f046ef8f942b48da1a281166ac810fed (diff)
FlagLines: use a shared updaters for options
previously, having two windows showing the same buffer with the same line flags would have updated the options twice, resulting in wrong lines in option. Now line flags options are updated only once by a shared object along all FlagLines highlighter using the same option.
Diffstat (limited to 'src')
-rw-r--r--src/highlighters.cc92
-rw-r--r--src/option_manager.hh2
2 files changed, 61 insertions, 33 deletions
diff --git a/src/highlighters.cc b/src/highlighters.cc
index fefee345..aef857c5 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -332,22 +332,22 @@ void expand_unprintable(DisplayBuffer& display_buffer)
}
}
-class FlagLines : public BufferChangeListener_AutoRegister,
- public OptionManagerWatcher_AutoRegister
+class FlagLines : public OptionManagerWatcher_AutoRegister
{
public:
FlagLines(Color bg, String option_name, Window& window)
- : BufferChangeListener_AutoRegister(window.buffer()),
- OptionManagerWatcher_AutoRegister(window.options()),
+ : OptionManagerWatcher_AutoRegister(window.options()),
m_bg(bg), m_option_name(std::move(option_name)),
m_window(window)
{
// trigger an exception if option is not of right type.
m_window.options()[m_option_name].get<std::vector<LineAndFlag>>();
+ update_shared_option_updater();
}
void operator()(DisplayBuffer& display_buffer)
{
+ update_shared_option_updater();
auto& lines = m_window.options()[m_option_name].get<std::vector<LineAndFlag>>();
CharCount width = 0;
@@ -366,54 +366,82 @@ public:
}
}
- void on_option_changed(const Option& option)
+private:
+ void on_option_changed(const Option& option) override
{
if (option.name() == m_option_name)
m_window.forget_timestamp();
}
- void on_insert(const BufferIterator& begin, const BufferIterator& end) override
+ struct OptionUpdater : BufferChangeListener_AutoRegister
{
- LineCount new_lines = end.line() - begin.line();
- if (new_lines == 0)
- return;
+ OptionUpdater(Buffer& buffer, Option& option)
+ : BufferChangeListener_AutoRegister(buffer), m_option(&option)
+ {
+ // sanity checks
+ kak_assert(&m_option->manager() != &GlobalOptions::instance());
+ m_option->get<std::vector<LineAndFlag>>();
+ }
- const Option& opt = m_window.options()[m_option_name];
- if (&opt.manager() == &GlobalOptions::instance())
- return;
- auto lines = opt.get<std::vector<LineAndFlag>>();
- for (auto& line : lines)
+ void on_insert(const BufferIterator& begin, const BufferIterator& end) override
{
- if (std::get<0>(line) > begin.line())
- std::get<0>(line) += new_lines;
+ LineCount new_lines = end.line() - begin.line();
+ if (new_lines == 0)
+ return;
+
+ auto lines = m_option->get<std::vector<LineAndFlag>>();
+ for (auto& line : lines)
+ {
+ if (std::get<0>(line) > begin.line())
+ std::get<0>(line) += new_lines;
+ }
+ m_option->set(lines);
}
- opt.manager().get_local_option(m_option_name).set(lines);
- }
- void on_erase(const BufferIterator& begin, const BufferIterator& end) override
- {
- LineCount removed_lines = end.line() - begin.line();
- if (removed_lines == 0)
- return;
+ void on_erase(const BufferIterator& begin, const BufferIterator& end) override
+ {
+ LineCount removed_lines = end.line() - begin.line();
+ if (removed_lines == 0)
+ return;
- const Option& opt = m_window.options()[m_option_name];
- // only update
- if (&opt.manager() == &GlobalOptions::instance())
+ auto lines = m_option->get<std::vector<LineAndFlag>>();
+ for (auto& line : lines)
+ {
+ if (std::get<0>(line) > begin.line())
+ std::get<0>(line) -= removed_lines;
+ }
+ m_option->set(lines);
+ }
+
+ const Option& option() const { return *m_option; }
+ private:
+ safe_ptr<Option> m_option;
+ };
+ static std::unordered_map<const Option*, std::weak_ptr<OptionUpdater>> ms_updaters;
+
+ void update_shared_option_updater()
+ {
+ const Option& option = m_window.options()[m_option_name];
+ if (&option.manager() == &GlobalOptions::instance() or
+ (m_updater and &option == &m_updater->option()))
return;
- auto lines = opt.get<std::vector<LineAndFlag>>();
- for (auto& line : lines)
+ auto& shared_updater = ms_updaters[&option];
+ if (shared_updater.expired())
{
- if (std::get<0>(line) > begin.line())
- std::get<0>(line) -= removed_lines;
+ m_updater = std::make_shared<OptionUpdater>(
+ m_window.buffer(), option.manager().get_local_option(option.name()));
+ shared_updater = m_updater;
}
- opt.manager().get_local_option(m_option_name).set(lines);
+ else
+ m_updater = shared_updater.lock();
}
-private:
Color m_bg;
String m_option_name;
Window& m_window;
+ std::shared_ptr<OptionUpdater> m_updater;
};
+std::unordered_map<const Option*, std::weak_ptr<FlagLines::OptionUpdater>> FlagLines::ms_updaters;
HighlighterAndId flag_lines_factory(const HighlighterParameters& params, Window& window)
{
diff --git a/src/option_manager.hh b/src/option_manager.hh
index b195d98a..b6688bf4 100644
--- a/src/option_manager.hh
+++ b/src/option_manager.hh
@@ -19,7 +19,7 @@ struct option_not_found : public runtime_error
class OptionManager;
-class Option
+class Option : public SafeCountable
{
public:
Option(OptionManager& manager, String name);