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)
|
PieceTable::Cursor::Cursor(PieceTable * pt) : iterator(pt)
|
||||||
{
|
{
|
||||||
line = iterator.valid() ? 1u : 0u;
|
line = 0u;
|
||||||
init_column();
|
init_column();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PieceTable::Cursor::go_start_of_line()
|
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.go_prev_piece();
|
||||||
}
|
}
|
||||||
|
iterator.offset = 0u;
|
||||||
init_column();
|
init_column();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PieceTable::Cursor::go_end_of_line()
|
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();
|
iterator.go_next_piece();
|
||||||
}
|
}
|
||||||
@ -201,8 +206,8 @@ bool PieceTable::Cursor::go_right(int n)
|
|||||||
uint32_t chr = *iterator;
|
uint32_t chr = *iterator;
|
||||||
if (chr == '\t')
|
if (chr == '\t')
|
||||||
{
|
{
|
||||||
column += iterator.piece_table->tabstop;
|
uint8_t tabstop = iterator.piece_table->tabstop;
|
||||||
column -= column % iterator.piece_table->tabstop;
|
column += tabstop - (column + 1u) % tabstop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -216,14 +221,15 @@ bool PieceTable::Cursor::is_start_of_line()
|
|||||||
{
|
{
|
||||||
return iterator.valid() &&
|
return iterator.valid() &&
|
||||||
(iterator.offset == 0u) &&
|
(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()
|
bool PieceTable::Cursor::is_end_of_line()
|
||||||
{
|
{
|
||||||
return iterator.valid() &&
|
return iterator.valid() &&
|
||||||
((iterator.offset + iterator.num_bytes_in_code_point()) >= iterator.piece->length) &&
|
((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
|
PieceTable::Piece * PieceTable::Cursor::prev_line() const
|
||||||
@ -268,7 +274,7 @@ void PieceTable::Cursor::init_column()
|
|||||||
{
|
{
|
||||||
uint32_t chr = *iterator;
|
uint32_t chr = *iterator;
|
||||||
/* TODO: handle multi-column characters */
|
/* 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()
|
void PieceTable::Cursor::calculate_column()
|
||||||
@ -286,6 +292,8 @@ void PieceTable::Cursor::calculate_column()
|
|||||||
void PieceTable::Cursor::forward_to_column(uint32_t c)
|
void PieceTable::Cursor::forward_to_column(uint32_t c)
|
||||||
{
|
{
|
||||||
int32_t diff = abs((int32_t)(c - column));
|
int32_t diff = abs((int32_t)(c - column));
|
||||||
|
if (diff == 0)
|
||||||
|
return;
|
||||||
while (go_right(1))
|
while (go_right(1))
|
||||||
{
|
{
|
||||||
int32_t new_diff = abs((int32_t)(c - column));
|
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_down(int n, uint32_t desired_column);
|
||||||
bool go_left(int n);
|
bool go_left(int n);
|
||||||
bool go_right(int n);
|
bool go_right(int n);
|
||||||
|
bool operator==(const Cursor & c)
|
||||||
|
{
|
||||||
|
return (c.line == line) && (c.column == column);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool is_start_of_line();
|
bool is_start_of_line();
|
||||||
|
@ -133,6 +133,7 @@ bool Window::create(std::shared_ptr<Buffer> buffer)
|
|||||||
m_buffer = buffer;
|
m_buffer = buffer;
|
||||||
m_cursor = m_buffer->piece_table->add_cursor();
|
m_cursor = m_buffer->piece_table->add_cursor();
|
||||||
m_start_piece = m_buffer->piece_table->start_piece->next;
|
m_start_piece = m_buffer->piece_table->start_piece->next;
|
||||||
|
m_cursor_row = 0;
|
||||||
|
|
||||||
resize();
|
resize();
|
||||||
|
|
||||||
@ -232,15 +233,45 @@ void Window::handle_key(uint32_t scancode, uint32_t mod)
|
|||||||
case SDL_SCANCODE_ESCAPE:
|
case SDL_SCANCODE_ESCAPE:
|
||||||
m_exit_requested = true;
|
m_exit_requested = true;
|
||||||
break;
|
break;
|
||||||
|
case SDL_SCANCODE_H:
|
||||||
|
cursor_left();
|
||||||
|
break;
|
||||||
case SDL_SCANCODE_J:
|
case SDL_SCANCODE_J:
|
||||||
scroll_down();
|
cursor_down();
|
||||||
break;
|
break;
|
||||||
case SDL_SCANCODE_K:
|
case SDL_SCANCODE_K:
|
||||||
scroll_up();
|
cursor_up();
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_L:
|
||||||
|
cursor_right();
|
||||||
break;
|
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()
|
void Window::scroll_down()
|
||||||
{
|
{
|
||||||
if ((m_start_piece != m_buffer->piece_table->end_piece) &&
|
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()
|
void Window::resize()
|
||||||
{
|
{
|
||||||
SDL_GetWindowSize(m_window, &m_width, &m_height);
|
SDL_GetWindowSize(m_window, &m_width, &m_height);
|
||||||
@ -280,52 +376,20 @@ void Window::redraw()
|
|||||||
glClearColor (0.0, 0.0, 0.0, 0.0);
|
glClearColor (0.0, 0.0, 0.0, 0.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
draw_cursor();
|
draw_text();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_SwapWindow(m_window);
|
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_cursor_array->bind();
|
||||||
m_shaders.flat->use();
|
m_shaders.flat->use();
|
||||||
m_shaders.flat->set_color(1.0, 0.2, 1.0, 1.0);
|
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);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef WINDOW_H
|
#ifndef WINDOW_H
|
||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include "TextShader.h"
|
#include "TextShader.h"
|
||||||
#include "FlatShader.h"
|
#include "FlatShader.h"
|
||||||
@ -17,11 +18,18 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void resize();
|
void resize();
|
||||||
void redraw();
|
void redraw();
|
||||||
void draw_cursor();
|
void draw_cursor(int screen_column, int screen_row);
|
||||||
void handle_event(SDL_Event & event);
|
void handle_event(SDL_Event & event);
|
||||||
void handle_key(uint32_t scancode, uint32_t mod);
|
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_down();
|
||||||
void scroll_up();
|
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;
|
SDL_Window * m_window;
|
||||||
bool m_exit_requested;
|
bool m_exit_requested;
|
||||||
@ -36,6 +44,7 @@ protected:
|
|||||||
Font m_font;
|
Font m_font;
|
||||||
int m_columns;
|
int m_columns;
|
||||||
int m_rows;
|
int m_rows;
|
||||||
|
int m_cursor_row;
|
||||||
|
|
||||||
std::shared_ptr<Buffer> m_buffer;
|
std::shared_ptr<Buffer> m_buffer;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user