diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-11-09 23:19:53 +0100 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2023-11-09 23:19:53 +0100 |
| commit | 1566b6faa8534118c3566188181367cd0868468f (patch) | |
| tree | 1de8d4b369efb5e592685a31088f798a6b63ffa1 /examples/dte/move.c | |
| parent | 349991bf6efe473ab9a5cbdae0a8114d72b997e3 (diff) | |
| download | crep-1566b6faa8534118c3566188181367cd0868468f.tar.gz | |
Added partial matching and introduced threads
Diffstat (limited to 'examples/dte/move.c')
| -rw-r--r-- | examples/dte/move.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/examples/dte/move.c b/examples/dte/move.c new file mode 100644 index 0000000..72414b3 --- /dev/null +++ b/examples/dte/move.c @@ -0,0 +1,311 @@ +#include "move.h" +#include "buffer.h" +#include "indent.h" +#include "util/ascii.h" +#include "util/debug.h" +#include "util/macros.h" +#include "util/utf8.h" + +typedef enum { + CT_SPACE, + CT_NEWLINE, + CT_WORD, + CT_OTHER, +} CharTypeEnum; + +void move_to_preferred_x(View *view, long preferred_x) +{ + const LocalOptions *options = &view->buffer->options; + StringView line; + view->preferred_x = preferred_x; + block_iter_bol(&view->cursor); + fill_line_ref(&view->cursor, &line); + + if (options->emulate_tab && view->preferred_x < line.length) { + const size_t iw = options->indent_width; + const size_t ilevel = indent_level(view->preferred_x, iw); + for (size_t i = 0; i < line.length && line.data[i] == ' '; i++) { + if (i + 1 == (ilevel + 1) * iw) { + // Force cursor to beginning of the indentation level + view->cursor.offset += ilevel * iw; + return; + } + } + } + + const unsigned int tw = options->tab_width; + unsigned long x = 0; + size_t i = 0; + while (x < view->preferred_x && i < line.length) { + CodePoint u = line.data[i++]; + if (likely(u < 0x80)) { + if (likely(!ascii_iscntrl(u))) { + x++; + } else if (u == '\t') { + x = next_indent_width(x, tw); + } else if (u == '\n') { + break; + } else { + x += 2; + } + } else { + const size_t next = i; + i--; + u = u_get_nonascii(line.data, line.length, &i); + x += u_char_width(u); + if (x > view->preferred_x) { + i = next; + break; + } + } + } + if (x > view->preferred_x) { + i--; + } + view->cursor.offset += i; + + // If cursor stopped on a zero-width char, move to the next spacing char + CodePoint u; + if (block_iter_get_char(&view->cursor, &u) && u_is_zero_width(u)) { + block_iter_next_column(&view->cursor); + } +} + +void move_cursor_left(View *view) +{ + const LocalOptions *options = &view->buffer->options; + if (options->emulate_tab) { + size_t size = get_indent_level_bytes_left(options, &view->cursor); + if (size) { + block_iter_back_bytes(&view->cursor, size); + view_reset_preferred_x(view); + return; + } + } + block_iter_prev_column(&view->cursor); + view_reset_preferred_x(view); +} + +void move_cursor_right(View *view) +{ + const LocalOptions *options = &view->buffer->options; + if (options->emulate_tab) { + size_t size = get_indent_level_bytes_right(options, &view->cursor); + if (size) { + block_iter_skip_bytes(&view->cursor, size); + view_reset_preferred_x(view); + return; + } + } + block_iter_next_column(&view->cursor); + view_reset_preferred_x(view); +} + +void move_bol(View *view) +{ + block_iter_bol(&view->cursor); + view_reset_preferred_x(view); +} + +void move_bol_smart(View *view, SmartBolFlags flags) +{ + if (flags == 0) { + move_bol(view); + return; + } + + BUG_ON(!(flags & BOL_SMART)); + bool fwd = false; + StringView line; + size_t cursor_offset = fetch_this_line(&view->cursor, &line); + + if (cursor_offset == 0) { + // Already at bol + if (!(flags & BOL_SMART_TOGGLE)) { + goto out; + } + fwd = true; + } + + size_t indent = ascii_blank_prefix_length(line.data, line.length); + if (fwd) { + block_iter_skip_bytes(&view->cursor, indent); + } else { + size_t co = cursor_offset; + size_t move = (co > indent) ? co - indent : co; + block_iter_back_bytes(&view->cursor, move); + } + +out: + view_reset_preferred_x(view); +} + +void move_eol(View *view) +{ + block_iter_eol(&view->cursor); + view_reset_preferred_x(view); +} + +void move_up(View *view, long count) +{ + const long x = view_get_preferred_x(view); + while (count > 0) { + if (!block_iter_prev_line(&view->cursor)) { + break; + } + count--; + } + move_to_preferred_x(view, x); +} + +void move_down(View *view, long count) +{ + const long x = view_get_preferred_x(view); + while (count > 0) { + if (!block_iter_eat_line(&view->cursor)) { + break; + } + count--; + } + move_to_preferred_x(view, x); +} + +void move_bof(View *view) +{ + block_iter_bof(&view->cursor); + view_reset_preferred_x(view); +} + +void move_eof(View *view) +{ + block_iter_eof(&view->cursor); + view_reset_preferred_x(view); +} + +void move_to_line(View *view, size_t line) +{ + BUG_ON(line == 0); + view->center_on_scroll = true; + block_iter_goto_line(&view->cursor, line - 1); +} + +void move_to_column(View *view, size_t column) +{ + BUG_ON(column == 0); + block_iter_bol(&view->cursor); + while (column-- > 1) { + CodePoint u; + if (!block_iter_next_char(&view->cursor, &u)) { + break; + } + if (u == '\n') { + block_iter_prev_char(&view->cursor, &u); + break; + } + } + view_reset_preferred_x(view); +} + +void move_to_filepos(View *view, size_t line, size_t column) +{ + move_to_line(view, line); + BUG_ON(!block_iter_is_bol(&view->cursor)); + if (column != 1) { + move_to_column(view, column); + } + view_reset_preferred_x(view); +} + +static CharTypeEnum get_char_type(CodePoint u) +{ + if (u == '\n') { + return CT_NEWLINE; + } + if (u_is_breakable_whitespace(u)) { + return CT_SPACE; + } + if (u_is_word_char(u)) { + return CT_WORD; + } + return CT_OTHER; +} + +static bool get_current_char_type(BlockIter *bi, CharTypeEnum *type) +{ + CodePoint u; + if (!block_iter_get_char(bi, &u)) { + return false; + } + + *type = get_char_type(u); + return true; +} + +static size_t skip_fwd_char_type(BlockIter *bi, CharTypeEnum type) +{ + size_t count = 0; + CodePoint u; + while (block_iter_next_char(bi, &u)) { + if (get_char_type(u) != type) { + block_iter_prev_char(bi, &u); + break; + } + count += u_char_size(u); + } + return count; +} + +static size_t skip_bwd_char_type(BlockIter *bi, CharTypeEnum type) +{ + size_t count = 0; + CodePoint u; + while (block_iter_prev_char(bi, &u)) { + if (get_char_type(u) != type) { + block_iter_next_char(bi, &u); + break; + } + count += u_char_size(u); + } + return count; +} + +size_t word_fwd(BlockIter *bi, bool skip_non_word) +{ + size_t count = 0; + CharTypeEnum type; + + while (1) { + count += skip_fwd_char_type(bi, CT_SPACE); + if (!get_current_char_type(bi, &type)) { + return count; + } + + if ( + count + && (!skip_non_word || (type == CT_WORD || type == CT_NEWLINE)) + ) { + return count; + } + + count += skip_fwd_char_type(bi, type); + } +} + +size_t word_bwd(BlockIter *bi, bool skip_non_word) +{ + size_t count = 0; + CharTypeEnum type; + CodePoint u; + + do { + count += skip_bwd_char_type(bi, CT_SPACE); + if (!block_iter_prev_char(bi, &u)) { + return count; + } + + type = get_char_type(u); + count += u_char_size(u); + count += skip_bwd_char_type(bi, type); + } while (skip_non_word && type != CT_WORD && type != CT_NEWLINE); + return count; +} |
