Draw text based on new cursor movement system
The cursor row still locked to the first row for now
This commit is contained in:
parent
01bf455e68
commit
86246385d4
@ -118,22 +118,27 @@ void PieceTable::Iterator::go_prev_piece()
|
||||
|
||||
PieceTable::Cursor::Cursor(PieceTable * pt) : iterator(pt)
|
||||
{
|
||||
line = iterator.valid() ? 1u : 0u;
|
||||
line = 0u;
|
||||
init_column();
|
||||
}
|
||||
|
||||
void PieceTable::Cursor::go_start_of_line()
|
||||
{
|
||||
while (iterator.valid() && (!iterator.piece->prev->eol()))
|
||||
while (iterator.valid() &&
|
||||
(!iterator.piece->prev->eol()) &&
|
||||
(iterator.piece->prev != iterator.piece_table->start_piece))
|
||||
{
|
||||
iterator.go_prev_piece();
|
||||
}
|
||||
iterator.offset = 0u;
|
||||
init_column();
|
||||
}
|
||||
|
||||
void PieceTable::Cursor::go_end_of_line()
|
||||
{
|
||||
while (iterator.valid() && (!iterator.piece->eol()))
|
||||
while (iterator.valid() &&
|
||||
(!iterator.piece->eol()) &&
|
||||
(iterator.piece->next != iterator.piece_table->end_piece))
|
||||
{
|
||||
iterator.go_next_piece();
|
||||
}
|
||||
@ -201,8 +206,8 @@ bool PieceTable::Cursor::go_right(int n)
|
||||
uint32_t chr = *iterator;
|
||||
if (chr == '\t')
|
||||
{
|
||||
column += iterator.piece_table->tabstop;
|
||||
column -= column % iterator.piece_table->tabstop;
|
||||
uint8_t tabstop = iterator.piece_table->tabstop;
|
||||
column += tabstop - (column + 1u) % tabstop;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -216,14 +221,15 @@ bool PieceTable::Cursor::is_start_of_line()
|
||||
{
|
||||
return iterator.valid() &&
|
||||
(iterator.offset == 0u) &&
|
||||
(iterator.piece->prev->eol());
|
||||
((iterator.piece->prev == iterator.piece_table->start_piece) ||
|
||||
iterator.piece->prev->eol());
|
||||
}
|
||||
|
||||
bool PieceTable::Cursor::is_end_of_line()
|
||||
{
|
||||
return iterator.valid() &&
|
||||
((iterator.offset + iterator.num_bytes_in_code_point()) >= iterator.piece->length) &&
|
||||
iterator.piece->eol();
|
||||
(iterator.piece->eol() || (iterator.piece->next == iterator.piece_table->end_piece));
|
||||
}
|
||||
|
||||
PieceTable::Piece * PieceTable::Cursor::prev_line() const
|
||||
@ -268,7 +274,7 @@ void PieceTable::Cursor::init_column()
|
||||
{
|
||||
uint32_t chr = *iterator;
|
||||
/* TODO: handle multi-column characters */
|
||||
column = (chr == 0xFFFFFFFFu) ? 0u : (chr == '\t') ? iterator.piece_table->tabstop : 1u;
|
||||
column = (chr == '\t') ? iterator.piece_table->tabstop - 1u : 0u;
|
||||
}
|
||||
|
||||
void PieceTable::Cursor::calculate_column()
|
||||
@ -286,6 +292,8 @@ void PieceTable::Cursor::calculate_column()
|
||||
void PieceTable::Cursor::forward_to_column(uint32_t c)
|
||||
{
|
||||
int32_t diff = abs((int32_t)(c - column));
|
||||
if (diff == 0)
|
||||
return;
|
||||
while (go_right(1))
|
||||
{
|
||||
int32_t new_diff = abs((int32_t)(c - column));
|
||||
|
@ -116,6 +116,10 @@ public:
|
||||
bool go_down(int n, uint32_t desired_column);
|
||||
bool go_left(int n);
|
||||
bool go_right(int n);
|
||||
bool operator==(const Cursor & c)
|
||||
{
|
||||
return (c.line == line) && (c.column == column);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool is_start_of_line();
|
||||
|
@ -133,6 +133,7 @@ bool Window::create(std::shared_ptr<Buffer> buffer)
|
||||
m_buffer = buffer;
|
||||
m_cursor = m_buffer->piece_table->add_cursor();
|
||||
m_start_piece = m_buffer->piece_table->start_piece->next;
|
||||
m_cursor_row = 0;
|
||||
|
||||
resize();
|
||||
|
||||
@ -232,15 +233,45 @@ void Window::handle_key(uint32_t scancode, uint32_t mod)
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
m_exit_requested = true;
|
||||
break;
|
||||
case SDL_SCANCODE_H:
|
||||
cursor_left();
|
||||
break;
|
||||
case SDL_SCANCODE_J:
|
||||
scroll_down();
|
||||
cursor_down();
|
||||
break;
|
||||
case SDL_SCANCODE_K:
|
||||
scroll_up();
|
||||
cursor_up();
|
||||
break;
|
||||
case SDL_SCANCODE_L:
|
||||
cursor_right();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::cursor_left()
|
||||
{
|
||||
m_cursor->go_left(1);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Window::cursor_right()
|
||||
{
|
||||
m_cursor->go_right(1);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Window::cursor_up()
|
||||
{
|
||||
m_cursor->go_up(1, m_cursor->column);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Window::cursor_down()
|
||||
{
|
||||
m_cursor->go_down(1, m_cursor->column);
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Window::scroll_down()
|
||||
{
|
||||
if ((m_start_piece != m_buffer->piece_table->end_piece) &&
|
||||
@ -261,6 +292,71 @@ void Window::scroll_up()
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<int, PieceTable::Cursor> Window::calculate_start_position()
|
||||
{
|
||||
m_cursor_row = std::min(m_cursor_row, m_rows - 1);
|
||||
int row = m_cursor_row - m_cursor->column / m_columns;
|
||||
PieceTable::Cursor cursor = *m_cursor;
|
||||
cursor.go_start_of_line();
|
||||
while (row > 0)
|
||||
{
|
||||
if (cursor.go_up(1, 0u))
|
||||
{
|
||||
PieceTable::Cursor c = cursor;
|
||||
c.go_end_of_line();
|
||||
row -= c.column / m_columns + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cursor_row -= row;
|
||||
row = 0;
|
||||
}
|
||||
}
|
||||
return std::pair<int, PieceTable::Cursor>(row, cursor);
|
||||
}
|
||||
|
||||
void Window::draw_text()
|
||||
{
|
||||
auto start_position = calculate_start_position();
|
||||
int row = start_position.first;
|
||||
PieceTable::Cursor cursor = start_position.second;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int row_offset = cursor.column / m_columns;
|
||||
int screen_row = row + row_offset;
|
||||
if (screen_row >= m_rows)
|
||||
break;
|
||||
int screen_column = cursor.column % m_columns;
|
||||
if (cursor == *m_cursor)
|
||||
draw_cursor(screen_column, screen_row);
|
||||
if (screen_row >= 0)
|
||||
{
|
||||
uint32_t character = *cursor;
|
||||
if (character != 0xFFFFFFFFu)
|
||||
draw_character(screen_column, screen_row, character);
|
||||
}
|
||||
if (!cursor.go_right(1))
|
||||
{
|
||||
if (!cursor.go_down(1, 0))
|
||||
break;
|
||||
row = screen_row + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::draw_character(int screen_column, int screen_row, uint32_t character)
|
||||
{
|
||||
m_shaders.text->use();
|
||||
int advance = m_font.get_advance();
|
||||
int line_height = m_font.get_line_height();
|
||||
int x = screen_column * advance;
|
||||
int y = m_height - (screen_row + 1) * line_height;
|
||||
auto g = m_font.get_glyph(character);
|
||||
m_shaders.text->set_position(x, y + m_font.get_baseline_offset());
|
||||
g->render();
|
||||
}
|
||||
|
||||
void Window::resize()
|
||||
{
|
||||
SDL_GetWindowSize(m_window, &m_width, &m_height);
|
||||
@ -280,52 +376,20 @@ void Window::redraw()
|
||||
glClearColor (0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
draw_cursor();
|
||||
m_shaders.text->use();
|
||||
|
||||
int advance = m_font.get_advance();
|
||||
int line_height = m_font.get_line_height();
|
||||
int x = 0;
|
||||
int y = m_height - line_height;
|
||||
for (PieceTable::Piece * piece = m_start_piece;
|
||||
piece != m_buffer->piece_table->end_piece;
|
||||
piece = piece->next)
|
||||
{
|
||||
for (int i = 0, len = piece->length; i < len; i++)
|
||||
{
|
||||
uint8_t c = piece->start[i];
|
||||
auto g = m_font.get_glyph(c);
|
||||
m_shaders.text->set_position(x, y + m_font.get_baseline_offset());
|
||||
g->render();
|
||||
if ((i + 1) % m_columns == 0)
|
||||
{
|
||||
y -= line_height;
|
||||
x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += advance;
|
||||
}
|
||||
}
|
||||
if (piece->eol())
|
||||
{
|
||||
y -= line_height;
|
||||
x = 0;
|
||||
}
|
||||
if (y + line_height < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
draw_text();
|
||||
|
||||
SDL_GL_SwapWindow(m_window);
|
||||
}
|
||||
|
||||
void Window::draw_cursor()
|
||||
void Window::draw_cursor(int screen_column, int screen_row)
|
||||
{
|
||||
int advance = m_font.get_advance();
|
||||
int line_height = m_font.get_line_height();
|
||||
int x = screen_column * advance;
|
||||
int y = m_height - (screen_row + 1) * line_height;
|
||||
m_cursor_array->bind();
|
||||
m_shaders.flat->use();
|
||||
m_shaders.flat->set_color(1.0, 0.2, 1.0, 1.0);
|
||||
m_shaders.flat->set_position(0, m_height - m_font.get_line_height());
|
||||
m_shaders.flat->set_position(x, y);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <utility>
|
||||
#include <SDL.h>
|
||||
#include "TextShader.h"
|
||||
#include "FlatShader.h"
|
||||
@ -17,11 +18,18 @@ public:
|
||||
protected:
|
||||
void resize();
|
||||
void redraw();
|
||||
void draw_cursor();
|
||||
void draw_cursor(int screen_column, int screen_row);
|
||||
void handle_event(SDL_Event & event);
|
||||
void handle_key(uint32_t scancode, uint32_t mod);
|
||||
void cursor_left();
|
||||
void cursor_right();
|
||||
void cursor_up();
|
||||
void cursor_down();
|
||||
void scroll_down();
|
||||
void scroll_up();
|
||||
std::pair<int, PieceTable::Cursor> calculate_start_position();
|
||||
void draw_text();
|
||||
void draw_character(int screen_column, int screen_row, uint32_t character);
|
||||
|
||||
SDL_Window * m_window;
|
||||
bool m_exit_requested;
|
||||
@ -36,6 +44,7 @@ protected:
|
||||
Font m_font;
|
||||
int m_columns;
|
||||
int m_rows;
|
||||
int m_cursor_row;
|
||||
|
||||
std::shared_ptr<Buffer> m_buffer;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user