diff --git a/src/buffer.cc b/src/buffer.cc index 62be491e..e40383cd 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -388,18 +388,16 @@ void Buffer::erase(BufferIterator begin, BufferIterator end) do_erase(begin, end); } -Window* Buffer::get_or_create_window() +Window& Buffer::new_window() { - if (m_windows.empty()) - m_windows.push_front(std::unique_ptr(new Window(*this))); - - return m_windows.front().get(); + m_windows.emplace_back(new Window(*this)); + return *m_windows.back(); } -void Buffer::delete_window(Window* window) +void Buffer::delete_window(Window& window) { - assert(&window->buffer() == this); - auto window_it = std::find(m_windows.begin(), m_windows.end(), window); + assert(&window.buffer() == this); + auto window_it = std::find(m_windows.begin(), m_windows.end(), &window); assert(window_it != m_windows.end()); m_windows.erase(window_it); } diff --git a/src/buffer.hh b/src/buffer.hh index d955bb14..f38de731 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -143,8 +143,11 @@ public: const String& name() const { return m_name; } - Window* get_or_create_window(); - void delete_window(Window* window); + // Window handling + using WindowList = std::vector>; + const WindowList& windows() const { return m_windows; } + Window& new_window(); + void delete_window(Window& window); // returns true if the buffer is in a different state than // the last time it was saved @@ -216,7 +219,7 @@ private: void apply_modification(const Modification& modification); void revert_modification(const Modification& modification); - std::list> m_windows; + WindowList m_windows; size_t m_last_save_undo_index; size_t m_timestamp; diff --git a/src/client_manager.cc b/src/client_manager.cc index 2d65402b..d60f49e8 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -8,7 +8,7 @@ namespace Kakoune void ClientManager::create_client(std::unique_ptr&& ui, Buffer& buffer, int event_fd) { - m_clients.emplace_back(std::move(ui), *buffer.get_or_create_window()); + m_clients.emplace_back(std::move(ui), get_unused_window_for_buffer(buffer)); InputHandler* input_handler = m_clients.back().input_handler.get(); Context* context = m_clients.back().context.get(); @@ -43,4 +43,18 @@ void ClientManager::remove_client_by_context(Context& context) assert(false); } +Window& ClientManager::get_unused_window_for_buffer(Buffer& buffer) const +{ + for (auto& w : buffer.windows()) + { + auto it = std::find_if(m_clients.begin(), m_clients.end(), + [&](const Client& client) { + return &client.context->window() == w.get(); + }); + if (it == m_clients.end()) + return *w; + } + return buffer.new_window(); +} + } diff --git a/src/client_manager.hh b/src/client_manager.hh index c43346cb..dab3b356 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -19,6 +19,8 @@ public: bool empty() const { return m_clients.empty(); } size_t count() const { return m_clients.size(); } + Window& get_unused_window_for_buffer(Buffer& buffer) const; + private: struct Client { diff --git a/src/commands.cc b/src/commands.cc index f6b3f767..cbbbbf54 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -282,13 +282,13 @@ void edit(const CommandParameters& params, Context& context) } BufferManager::instance().set_last_used_buffer(*buffer); - Window& window = *buffer->get_or_create_window(); + Window& window = ClientManager::instance().get_unused_window_for_buffer(*buffer); if (param_count > 1) { int line = std::max(0, str_to_int(parser[1]) - 1); int column = param_count > 2 ? - std::max(0, str_to_int(parser[2]) - 1) : 0; + std::max(0, str_to_int(parser[2]) - 1) : 0; window.select(window.buffer().iterator_at({ line, column })); window.center_selection(); @@ -378,7 +378,8 @@ void show_buffer(const CommandParameters& params, Context& context) throw runtime_error("buffer " + buffer_name + " does not exists"); BufferManager::instance().set_last_used_buffer(*buffer); - context.change_editor(*buffer->get_or_create_window()); + Window& window = ClientManager::instance().get_unused_window_for_buffer(*buffer); + context.change_editor(window); } void delete_buffer(const CommandParameters& params, Context& context) @@ -408,7 +409,8 @@ void delete_buffer(const CommandParameters& params, Context& context) { if (buf != buffer) { - context.change_editor(*buf->get_or_create_window()); + Window& w = ClientManager::instance().get_unused_window_for_buffer(*buf); + context.change_editor(w); break; } }