move character iteration logic from BufferView to BufferLineWalker
This commit is contained in:
parent
65df0c2320
commit
3d4e8230fe
101
src/core/BufferLineWalker.cc
Normal file
101
src/core/BufferLineWalker.cc
Normal file
@ -0,0 +1,101 @@
|
||||
#include "BufferLineWalker.h"
|
||||
|
||||
/**
|
||||
* Construct a BufferLineWalker.
|
||||
*/
|
||||
BufferLineWalker::BufferLineWalker(
|
||||
std::shared_ptr<Buffer> buffer,
|
||||
CharacterWidthDeterminer & character_width_determiner)
|
||||
: m_buffer(buffer),
|
||||
m_character_width_determiner(character_width_determiner)
|
||||
{
|
||||
m_width = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the view width.
|
||||
*
|
||||
* @param width View width.
|
||||
*/
|
||||
void BufferLineWalker::set_width(int width)
|
||||
{
|
||||
m_width = std::max(1, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the callback for each character in the buffer line, wrapping to the
|
||||
* next screen line and taking into account multi-column characters.
|
||||
*
|
||||
* Callback parameters:
|
||||
* - row_offset
|
||||
* - screen column
|
||||
* - virtual column
|
||||
* - character width
|
||||
* - buffer iterator
|
||||
* If the callback function returns true, iteration continues. Otherwise
|
||||
* iteration is terminated.
|
||||
*
|
||||
* @param start_of_line Buffer iterator pointing to the beginning of the buffer line.
|
||||
* @param callback Function to call for each character in the line.
|
||||
*/
|
||||
void BufferLineWalker::walk_line(
|
||||
const Buffer::Iterator & start_of_line,
|
||||
std::function<bool(int, int, int, int, const Buffer::Iterator &)> callback)
|
||||
{
|
||||
int row_offset = 0;
|
||||
int screen_column = 0;
|
||||
int virtual_column = 0;
|
||||
Buffer::Iterator i = start_of_line;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t code_point = *i;
|
||||
if ((code_point == '\n') || (!i.valid()))
|
||||
{
|
||||
callback(row_offset, screen_column, virtual_column, 0, i);
|
||||
break;
|
||||
}
|
||||
int c_width;
|
||||
if (code_point == '\t')
|
||||
{
|
||||
uint8_t tabstop = m_buffer->tabstop();
|
||||
c_width = tabstop - virtual_column % tabstop;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_width = m_character_width_determiner(code_point);
|
||||
if (((screen_column + c_width) > m_width) &&
|
||||
(screen_column > 0))
|
||||
{
|
||||
row_offset++;
|
||||
screen_column = 0;
|
||||
}
|
||||
}
|
||||
if (!callback(row_offset, screen_column, virtual_column, c_width, i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
virtual_column += c_width;
|
||||
if (code_point == '\t')
|
||||
{
|
||||
screen_column += c_width;
|
||||
while (screen_column >= m_width)
|
||||
{
|
||||
screen_column -= m_width;
|
||||
row_offset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((screen_column + c_width) >= m_width)
|
||||
{
|
||||
row_offset++;
|
||||
screen_column = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
screen_column += c_width;
|
||||
}
|
||||
}
|
||||
i.go_forward();
|
||||
}
|
||||
}
|
29
src/core/BufferLineWalker.h
Normal file
29
src/core/BufferLineWalker.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef BUFFERLINEWALKER_H
|
||||
#define BUFFERLINEWALKER_H
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "CharacterWidthDeterminer.h"
|
||||
#include <functional>
|
||||
|
||||
/**
|
||||
* Provides functionality to walk a line of a buffer taking into account the
|
||||
* view width and multi-column characters.
|
||||
*/
|
||||
class BufferLineWalker
|
||||
{
|
||||
public:
|
||||
BufferLineWalker(
|
||||
std::shared_ptr<Buffer> buffer,
|
||||
CharacterWidthDeterminer & character_width_determiner);
|
||||
void set_width(int width);
|
||||
void walk_line(
|
||||
const Buffer::Iterator & start_of_line,
|
||||
std::function<bool(int, int, int, int, const Buffer::Iterator &)> callback);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Buffer> m_buffer;
|
||||
CharacterWidthDeterminer & m_character_width_determiner;
|
||||
int m_width;
|
||||
};
|
||||
|
||||
#endif
|
@ -23,60 +23,3 @@ void BufferView::set_scroll_offset(int scroll_offset)
|
||||
{
|
||||
m_scroll_offset = std::max(0, scroll_offset);
|
||||
}
|
||||
|
||||
void BufferView::iter_cols(const Buffer::Iterator & start_of_line, std::function<void(int, int, int, int, const Buffer::Iterator &)> callback)
|
||||
{
|
||||
int row_offset = 0;
|
||||
int screen_column = 0;
|
||||
int virtual_column = 0;
|
||||
Buffer::Iterator i = start_of_line;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t code_point = *i;
|
||||
if ((code_point == '\n') || (!i.valid()))
|
||||
{
|
||||
callback(row_offset, screen_column, virtual_column, 0, i);
|
||||
break;
|
||||
}
|
||||
int c_width;
|
||||
if (code_point == '\t')
|
||||
{
|
||||
uint8_t tabstop = m_buffer->tabstop();
|
||||
c_width = tabstop - virtual_column % tabstop;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_width = m_character_width_determiner(code_point);
|
||||
if (((screen_column + c_width) > m_width) &&
|
||||
(screen_column > 0))
|
||||
{
|
||||
row_offset++;
|
||||
screen_column = 0;
|
||||
}
|
||||
}
|
||||
callback(row_offset, screen_column, virtual_column, c_width, i);
|
||||
virtual_column += c_width;
|
||||
if (code_point == '\t')
|
||||
{
|
||||
screen_column += c_width;
|
||||
while (screen_column >= m_width)
|
||||
{
|
||||
screen_column -= m_width;
|
||||
row_offset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((screen_column + c_width) >= m_width)
|
||||
{
|
||||
row_offset++;
|
||||
screen_column = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
screen_column += c_width;
|
||||
}
|
||||
}
|
||||
i.go_forward();
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ public:
|
||||
void resize(int width, int height);
|
||||
void set_scroll_offset(int scroll_offset);
|
||||
void iter_lines(std::function<bool(const Buffer::Iterator &)> callback);
|
||||
void iter_cols(const Buffer::Iterator & start_of_line, std::function<void(int, int, int, int, const Buffer::Iterator &)> callback);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Buffer> m_buffer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user