Draw text based on new cursor movement system

The cursor row still locked to the first row for now
This commit is contained in:
Josh Holtrop 2016-09-06 21:05:24 -04:00
parent 01bf455e68
commit 86246385d4
4 changed files with 135 additions and 50 deletions

View File

@ -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));

View File

@ -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();

View File

@ -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);
}

View File

@ -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;