From b5d121dc1ca4edc0cfff888ba411f0837e6e0ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Mon, 25 Aug 2014 18:47:00 +0200 Subject: Move motion related stuff into own file --- Makefile | 7 +- editor.c | 205 +++++++-------------------------------------------- editor.h | 10 ++- text-motions.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ text-motions.h | 58 +++++++++++++++ text-objects.c | 38 ++++++++++ text-objects.h | 13 ++++ text.c | 4 + text.h | 11 +++ 9 files changed, 389 insertions(+), 185 deletions(-) create mode 100644 text-motions.c create mode 100644 text-motions.h create mode 100644 text-objects.c create mode 100644 text-objects.h diff --git a/Makefile b/Makefile index 2bcc82e..cd0ca71 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ include config.mk -SRC += vis.c colors.c editor.c text.c +SRC += vis.c colors.c editor.c text.c text-motions.c text-objects.c +ALL = ${SRC} util.h editor.h text.h text-motions.h text-objects.h \ + config.def.h config.mk Makefile LICENSE README vis.1 OBJ = ${SRC:.c=.o} all: clean options vis @@ -36,8 +38,7 @@ clean: dist: clean @echo creating dist tarball @mkdir -p vis-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ - ${SRC} editor.h text.h util.h vis.1 vis-${VERSION} + @cp -R ${ALL} vis-${VERSION} @tar -cf vis-${VERSION}.tar vis-${VERSION} @gzip vis-${VERSION}.tar @rm -rf vis-${VERSION} diff --git a/editor.c b/editor.c index 009511d..78f7916 100644 --- a/editor.c +++ b/editor.c @@ -21,6 +21,8 @@ #include #include "editor.h" #include "text.h" +#include "text-motions.h" +#include "text-objects.h" #include "util.h" typedef struct { /* used to calculate the display width of a character */ @@ -729,23 +731,7 @@ size_t editor_line_down(Editor *ed) { } static size_t window_line_begin(Win *win) { - char c; - size_t pos = win->cursor.pos; - Iterator it = text_iterator_get(win->text, pos); - if (!text_iterator_byte_get(&it, &c)) - return pos; - if (c == '\r') - text_iterator_byte_prev(&it, &c); - if (c == '\n') - text_iterator_byte_prev(&it, &c); - while (text_iterator_byte_get(&it, &c)) { - if (c == '\n' || c == '\r') { - it.pos++; - break; - } - text_iterator_byte_prev(&it, NULL); - } - return cursor_move_to(win, it.pos); + return cursor_move_to(win, text_line_begin(win->text, win->cursor.pos)); } size_t editor_line_begin(Editor *ed) { @@ -753,213 +739,76 @@ size_t editor_line_begin(Editor *ed) { } size_t editor_line_start(Editor *ed) { - char c; Win *win = ed->win; - editor_line_begin(ed); - Iterator it = text_iterator_get(win->text, win->cursor.pos); - while (text_iterator_byte_get(&it, &c) && c != '\n' && isspace(c)) - text_iterator_byte_next(&it, NULL); - while (win->end < it.pos && scroll_line_down(win, 1)); - return cursor_move_to(win, it.pos); + size_t pos = text_line_start(win->text, win->cursor.pos); + while (win->end < pos && scroll_line_down(win, 1)); + return cursor_move_to(win, pos); } size_t editor_line_end(Editor *ed) { - char c; Win *win = ed->win; - Iterator it = text_iterator_get(win->text, win->cursor.pos); - while (text_iterator_byte_get(&it, &c) && c != '\n') - text_iterator_byte_next(&it, NULL); - while (win->end < it.pos && scroll_line_down(win, 1)); - return cursor_move_to(win, it.pos); + size_t pos = text_line_end(win->text, win->cursor.pos); + while (win->end < pos && scroll_line_down(win, 1)); + return cursor_move_to(win, pos); } size_t editor_line_finish(Editor *ed) { - char c; Win *win = ed->win; - Iterator it = text_iterator_get(win->text, editor_line_end(ed)); - do text_iterator_byte_prev(&it, NULL); - while (text_iterator_byte_get(&it, &c) && c != '\n' && c != '\r' && isspace(c)); - return cursor_move_to(win, it.pos); + size_t pos = text_line_finish(win->text, win->cursor.pos); + return cursor_move_to(win, pos); } size_t editor_word_end_prev(Editor *ed) { - char c; Win *win = ed->win; - Iterator it = text_iterator_get(win->text, win->cursor.pos); - while (text_iterator_byte_prev(&it, &c) && !isspace(c)); - while (text_iterator_char_prev(&it, &c) && isspace(c)); - while (win->start > it.pos && scroll_line_up(win, 1)); - return cursor_move_to(win, it.pos); + size_t pos = text_word_end_prev(win->text, win->cursor.pos); + while (win->start > pos && scroll_line_up(win, 1)); + return cursor_move_to(win, pos); } size_t editor_word_end_next(Editor *ed) { - char c; Win *win = ed->win; - size_t pos = win->cursor.pos; - Iterator it = text_iterator_get(win->text, pos); - while (text_iterator_char_next(&it, &c) && isspace(c)); - do pos = it.pos; while (text_iterator_char_next(&it, &c) && !isspace(c)); + size_t pos = text_word_end_next(win->text, win->cursor.pos); while (win->end < pos && scroll_line_down(win, 1)); return cursor_move_to(win, pos); } size_t editor_word_start_next(Editor *ed) { - char c; Win *win = ed->win; - Iterator it = text_iterator_get(win->text, win->cursor.pos); - while (text_iterator_byte_get(&it, &c) && !isspace(c)) - text_iterator_byte_next(&it, NULL); - while (text_iterator_byte_get(&it, &c) && isspace(c)) - text_iterator_byte_next(&it, NULL); - while (win->end < it.pos && scroll_line_down(win, 1)); - return cursor_move_to(win, it.pos); + size_t pos = text_word_start_next(win->text, win->cursor.pos); + while (win->end < pos && scroll_line_down(win, 1)); + return cursor_move_to(win, pos); } size_t editor_word_start_prev(Editor *ed) { - char c; Win *win = ed->win; - size_t pos = win->cursor.pos; - Iterator it = text_iterator_get(win->text, pos); - while (text_iterator_byte_prev(&it, &c) && isspace(c)); - do pos = it.pos; while (text_iterator_char_prev(&it, &c) && !isspace(c)); + size_t pos = text_word_start_prev(win->text, win->cursor.pos); while (win->start > pos && scroll_line_up(win, 1)); return cursor_move_to(win, pos); } -static size_t editor_paragraph_sentence_next(Editor *ed, bool sentence) { - char c; - bool content = false, paragraph = false; - Win *win = ed->win; - size_t pos = win->cursor.pos; - Iterator it = text_iterator_get(win->text, pos); - while (text_iterator_byte_next(&it, &c)) { - content |= !isspace(c); - if (sentence && (c == '.' || c == '?' || c == '!') && text_iterator_byte_next(&it, &c) && isspace(c)) { - if (c == '\n' && text_iterator_byte_next(&it, &c)) { - if (c == '\r') - text_iterator_byte_next(&it, &c); - } else { - while (text_iterator_byte_get(&it, &c) && c == ' ') - text_iterator_byte_next(&it, NULL); - } - break; - } - if (c == '\n' && text_iterator_byte_next(&it, &c)) { - if (c == '\r') - text_iterator_byte_next(&it, &c); - content |= !isspace(c); - if (c == '\n') - paragraph = true; - } - if (content && paragraph) - break; - } - while (win->end < it.pos && scroll_line_down(win, 1)); - return cursor_move_to(win, it.pos); -} - size_t editor_sentence_next(Editor *ed) { - return editor_paragraph_sentence_next(ed, true); + Win *win = ed->win; + return cursor_move_to_line(win, text_sentence_next(win->text, win->cursor.pos)); } size_t editor_paragraph_next(Editor *ed) { - return editor_paragraph_sentence_next(ed, false); -} - -static size_t editor_paragraph_sentence_prev(Editor *ed, bool sentence) { - char prev, c; - bool content = false, paragraph = false; Win *win = ed->win; - size_t pos = win->cursor.pos; - - Iterator it = text_iterator_get(win->text, pos); - if (!text_iterator_byte_get(&it, &prev)) - return pos; - - while (text_iterator_byte_prev(&it, &c)) { - content |= !isspace(c) && c != '.' && c != '?' && c != '!'; - if (sentence && content && (c == '.' || c == '?' || c == '!') && isspace(prev)) { - do text_iterator_byte_next(&it, NULL); - while (text_iterator_byte_get(&it, &c) && isspace(c)); - break; - } - if (c == '\r') - text_iterator_byte_prev(&it, &c); - if (c == '\n' && text_iterator_byte_prev(&it, &c)) { - content |= !isspace(c); - if (c == '\r') - text_iterator_byte_prev(&it, &c); - if (c == '\n') { - paragraph = true; - if (content) { - do text_iterator_byte_next(&it, NULL); - while (text_iterator_byte_get(&it, &c) && isspace(c)); - break; - } - } - } - if (content && paragraph) { - do text_iterator_byte_next(&it, NULL); - while (text_iterator_byte_get(&it, &c) && !isspace(c)); - break; - } - prev = c; - } - while (win->end < it.pos && scroll_line_down(win, 1)); - return cursor_move_to(win, it.pos); + return cursor_move_to_line(win, text_paragraph_next(win->text, win->cursor.pos)); } size_t editor_sentence_prev(Editor *ed) { - return editor_paragraph_sentence_prev(ed, true); + Win *win = ed->win; + return cursor_move_to_line(win, text_sentence_prev(win->text, win->cursor.pos)); } size_t editor_paragraph_prev(Editor *ed) { - return editor_paragraph_sentence_prev(ed, false); + Win *win = ed->win; + return cursor_move_to_line(win, text_paragraph_prev(win->text, win->cursor.pos)); } size_t editor_bracket_match(Editor *ed) { Win *win = ed->win; - int direction, count = 1; - char search, current, c; - size_t pos = win->cursor.pos; - Iterator it = text_iterator_get(win->text, pos); - if (!text_iterator_byte_get(&it, ¤t)) - return pos; - - switch (current) { - case '(': search = ')'; direction = 1; break; - case ')': search = '('; direction = -1; break; - case '{': search = '}'; direction = 1; break; - case '}': search = '{'; direction = -1; break; - case '[': search = ']'; direction = 1; break; - case ']': search = '['; direction = -1; break; - case '<': search = '>'; direction = 1; break; - case '>': search = '<'; direction = -1; break; - case '"': search = '"'; direction = 1; break; - default: return pos; - } - - if (direction >= 0) { /* forward search */ - while (text_iterator_byte_next(&it, &c)) { - if (c == search && --count == 0) { - pos = it.pos; - break; - } else if (c == current) { - count++; - } - } - } else { /* backwards */ - while (text_iterator_byte_prev(&it, &c)) { - if (c == search && --count == 0) { - pos = it.pos; - break; - } else if (c == current) { - count++; - } - } - } - - return cursor_move_to_line(win, pos); + return cursor_move_to_line(win, text_bracket_match(win->text, win->cursor.pos)); } void editor_draw(Editor *ed) { diff --git a/editor.h b/editor.h index d36e503..f141963 100644 --- a/editor.h +++ b/editor.h @@ -1,5 +1,9 @@ +#ifndef EDITOR_H +#define EDITOR_H + #include #include +#include "text.h" typedef struct { short fg, bg; /* fore and background color */ @@ -25,10 +29,6 @@ typedef struct { /* a syntax definition */ typedef struct Editor Editor; typedef size_t Filepos; -typedef struct { - Filepos start, end; /* range in bytes from start of file */ -} Filerange; - typedef void (*editor_statusbar_t)(WINDOW *win, bool active, const char *filename, int line, int col); /* initialize a new editor with the available screen size */ @@ -102,3 +102,5 @@ void editor_init(void); // TODO: comment short editor_color_reserve(short fg, short bg); short editor_color_get(short fg, short bg); + +#endif diff --git a/text-motions.c b/text-motions.c new file mode 100644 index 0000000..1313c94 --- /dev/null +++ b/text-motions.c @@ -0,0 +1,228 @@ +#include +#include "text-motions.h" + +// TODO: consistent usage of iterators either char or byte based where appropriate. + +size_t text_line_begin(Text *txt, size_t pos) { + char c; + Iterator it = text_iterator_get(txt, pos); + if (!text_iterator_byte_get(&it, &c)) + return pos; + if (c == '\r') + text_iterator_byte_prev(&it, &c); + if (c == '\n') + text_iterator_byte_prev(&it, &c); + while (text_iterator_byte_get(&it, &c)) { + if (c == '\n' || c == '\r') { + it.pos++; + break; + } + text_iterator_byte_prev(&it, NULL); + } + return pos; +} + +size_t text_line_start(Text *txt, size_t pos) { + char c; + Iterator it = text_iterator_get(txt, text_line_begin(txt, pos)); + while (text_iterator_byte_get(&it, &c) && c != '\n' && isspace(c)) + text_iterator_byte_next(&it, NULL); + return it.pos; +} + +size_t text_line_finish(Text *txt, size_t pos) { + char c; + Iterator it = text_iterator_get(txt, text_line_end(txt, pos)); + do text_iterator_byte_prev(&it, NULL); + while (text_iterator_byte_get(&it, &c) && c != '\n' && c != '\r' && isspace(c)); + return it.pos; +} + +size_t text_line_end(Text *txt, size_t pos) { + char c; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_byte_get(&it, &c) && c != '\n') + text_iterator_byte_next(&it, NULL); + return it.pos; +} + + +size_t text_word_boundry_start_next(Text *txt, size_t pos, int (*isboundry)(int)) { + char c; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_byte_get(&it, &c) && !isboundry(c)) + text_iterator_byte_next(&it, NULL); + while (text_iterator_byte_get(&it, &c) && isboundry(c)) + text_iterator_byte_next(&it, NULL); + return it.pos; +} + +size_t text_word_boundry_start_prev(Text *txt, size_t pos, int (*isboundry)(int)) { + char c; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_byte_prev(&it, &c) && isboundry(c)); + do pos = it.pos; while (text_iterator_char_prev(&it, &c) && !isboundry(c)); + return pos; +} + +size_t text_word_boundry_end_next(Text *txt, size_t pos, int (*isboundry)(int)) { + char c; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_char_next(&it, &c) && isboundry(c)); + do pos = it.pos; while (text_iterator_char_next(&it, &c) && !isboundry(c)); + return pos; +} + +size_t text_word_boundry_end_prev(Text *txt, size_t pos, int (*isboundry)(int)) { + char c; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_byte_prev(&it, &c) && !isboundry(c)); + while (text_iterator_char_prev(&it, &c) && isboundry(c)); + return it.pos; +} + +size_t text_word_end_next(Text *txt, size_t pos) { + return text_word_boundry_end_next(txt, pos, isspace); +} + +size_t text_word_end_prev(Text *txt, size_t pos) { + return text_word_boundry_end_prev(txt, pos, isspace); +} + +size_t text_word_start_next(Text *txt, size_t pos) { + return text_word_boundry_start_next(txt, pos, isspace); +} + +size_t text_word_start_prev(Text *txt, size_t pos) { + return text_word_boundry_start_prev(txt, pos, isspace); +} + +static size_t text_paragraph_sentence_next(Text *txt, size_t pos, bool sentence) { + char c; + bool content = false, paragraph = false; + Iterator it = text_iterator_get(txt, pos); + while (text_iterator_byte_next(&it, &c)) { + content |= !isspace(c); + if (sentence && (c == '.' || c == '?' || c == '!') && text_iterator_byte_next(&it, &c) && isspace(c)) { + if (c == '\n' && text_iterator_byte_next(&it, &c)) { + if (c == '\r') + text_iterator_byte_next(&it, &c); + } else { + while (text_iterator_byte_get(&it, &c) && c == ' ') + text_iterator_byte_next(&it, NULL); + } + break; + } + if (c == '\n' && text_iterator_byte_next(&it, &c)) { + if (c == '\r') + text_iterator_byte_next(&it, &c); + content |= !isspace(c); + if (c == '\n') + paragraph = true; + } + if (content && paragraph) + break; + } + return it.pos; +} + +static size_t text_paragraph_sentence_prev(Text *txt, size_t pos, bool sentence) { + char prev, c; + bool content = false, paragraph = false; + + Iterator it = text_iterator_get(txt, pos); + if (!text_iterator_byte_get(&it, &prev)) + return pos; + + while (text_iterator_byte_prev(&it, &c)) { + content |= !isspace(c) && c != '.' && c != '?' && c != '!'; + if (sentence && content && (c == '.' || c == '?' || c == '!') && isspace(prev)) { + do text_iterator_byte_next(&it, NULL); + while (text_iterator_byte_get(&it, &c) && isspace(c)); + break; + } + if (c == '\r') + text_iterator_byte_prev(&it, &c); + if (c == '\n' && text_iterator_byte_prev(&it, &c)) { + content |= !isspace(c); + if (c == '\r') + text_iterator_byte_prev(&it, &c); + if (c == '\n') { + paragraph = true; + if (content) { + do text_iterator_byte_next(&it, NULL); + while (text_iterator_byte_get(&it, &c) && isspace(c)); + break; + } + } + } + if (content && paragraph) { + do text_iterator_byte_next(&it, NULL); + while (text_iterator_byte_get(&it, &c) && !isspace(c)); + break; + } + prev = c; + } + return it.pos; +} + +size_t text_sentence_next(Text *txt, size_t pos) { + return text_paragraph_sentence_next(txt, pos, true); +} + +size_t text_sentence_prev(Text *txt, size_t pos) { + return text_paragraph_sentence_prev(txt, pos, true); +} + +size_t text_paragraph_next(Text *txt, size_t pos) { + return text_paragraph_sentence_next(txt, pos, false); +} + +size_t text_paragraph_prev(Text *txt, size_t pos) { + return text_paragraph_sentence_prev(txt, pos, false); +} + +size_t text_bracket_match(Text *txt, size_t pos) { + int direction, count = 1; + char search, current, c; + Iterator it = text_iterator_get(txt, pos); + if (!text_iterator_byte_get(&it, ¤t)) + return pos; + + switch (current) { + case '(': search = ')'; direction = 1; break; + case ')': search = '('; direction = -1; break; + case '{': search = '}'; direction = 1; break; + case '}': search = '{'; direction = -1; break; + case '[': search = ']'; direction = 1; break; + case ']': search = '['; direction = -1; break; + case '<': search = '>'; direction = 1; break; + case '>': search = '<'; direction = -1; break; + // TODO: heuristic basic on neighbouring chars shared with text-object + case '"': search = '"'; direction = 1; break; + case '\'': search = '\''; direction = 1; break; + default: return pos; + } + + if (direction >= 0) { /* forward search */ + while (text_iterator_byte_next(&it, &c)) { + if (c == search && --count == 0) { + pos = it.pos; + break; + } else if (c == current) { + count++; + } + } + } else { /* backwards */ + while (text_iterator_byte_prev(&it, &c)) { + if (c == search && --count == 0) { + pos = it.pos; + break; + } else if (c == current) { + count++; + } + } + } + + return pos; +} diff --git a/text-motions.h b/text-motions.h new file mode 100644 index 0000000..bbeca49 --- /dev/null +++ b/text-motions.h @@ -0,0 +1,58 @@ +#ifndef TEXT_MOTIONS_H +#define TEXT_MOTIONS_H + +#include +#include "text.h" + +/* begin finish + * v v + * | I am a line! | + * ^ ^ + * start end + */ +size_t text_line_begin(Text*, size_t pos); +size_t text_line_start(Text*, size_t pos); +size_t text_line_finish(Text*, size_t pos); +size_t text_line_end(Text*, size_t pos); +/* + * A word consists of a sequence of non-blank characters, separated with white space. + * TODO?: An empty line is also considered to be a word. This is equivalant to a WORD + * in vim terminology. + */ +size_t text_word_end_next(Text*, size_t pos); +size_t text_word_end_prev(Text*, size_t pos); +size_t text_word_start_next(Text*, size_t pos); +size_t text_word_start_prev(Text*, size_t pos); +/* + * These are variants of the above with the additional possibility to implement + * a custom word detection logic. Can be used to implment the equivalent of a what + * vim reconizes as a word (lowercase). + */ +size_t text_word_boundry_end_next(Text*, size_t pos, int (*isboundry)(int)); +size_t text_word_boundry_end_prev(Text*, size_t pos, int (*isboundry)(int)); +size_t text_word_boundry_start_next(Text*, size_t pos, int (*isboundry)(int)); +size_t text_word_boundry_start_prev(Text*, size_t pos, int (*isboundry)(int)); +/* TODO: implement the following semantics + * A sentence is defined as ending at a '.', '!' or '?' followed by either the + * end of a line, or by a space or tab. Any number of closing ')', ']', '"' + * and ''' characters may appear after the '.', '!' or '?' before the spaces, + * tabs or end of line. A paragraph and section boundary is also a sentence + * boundary. + */ +size_t text_sentence_next(Text*, size_t pos); +size_t text_sentence_prev(Text*, size_t pos); +/* TODO: implement the following semantics + * A paragraph begins after each empty line. A section boundary is also a + * paragraph boundary. Note that a blank line (only containing white space) + * is NOT a paragraph boundary. + */ +size_t text_paragraph_next(Text*, size_t pos); +size_t text_paragraph_prev(Text*, size_t pos); +/* A section begins after a form-feed in the first column. +size_t text_section_next(Text*, size_t pos); +size_t text_section_prev(Text*, size_t pos); +*/ +/* search coresponding '(', ')', '{', '}', '[', ']', '>', '<', '"', ''' */ +size_t text_bracket_match(Text*, size_t pos); + +#endif diff --git a/text-objects.c b/text-objects.c new file mode 100644 index 0000000..d6ac4a3 --- /dev/null +++ b/text-objects.c @@ -0,0 +1,38 @@ +#include +#include "text-motions.h" +#include "text-objects.h" + +static Filerange empty = { + .start = -1, + .end = -1, +}; + +// TODO: fix problems with inclusive / exclusive +Filerange text_object_word(Text *txt, size_t pos) { + char c; + Filerange r; + if (!text_byte_get(txt, pos, &c)) + return empty; + if (!isspace(c)) { + r.start = text_word_start_prev(txt, pos); + r.end = text_word_end_next(txt, pos); + } else { + r.start = text_word_end_prev(txt, pos); + r.end = text_word_start_next(txt, pos); + } + return r; +} + +Filerange text_object_sentence(Text *txt, size_t pos) { + Filerange r; + r.start = text_sentence_prev(txt, pos); + r.end = text_sentence_next(txt, pos); + return r; +} + +Filerange text_object_paragraph(Text *txt, size_t pos) { + Filerange r; + r.start = text_paragraph_prev(txt, pos); + r.end = text_paragraph_next(txt, pos); + return r; +} diff --git a/text-objects.h b/text-objects.h new file mode 100644 index 0000000..62d30e5 --- /dev/null +++ b/text-objects.h @@ -0,0 +1,13 @@ +#ifndef TEXT_OBJECTS_H +#define TEXT_OBJECTS_H + +#include +#include "text.h" + +Filerange text_object_word(Text*, size_t pos); +Filerange text_object_word_boundry(Text*, size_t pos, int (*isboundry)(int)); +Filerange text_object_char(Text*, size_t pos, char c); +Filerange text_object_sentence(Text*, size_t pos); +Filerange text_object_paragraph(Text*, size_t pos); + +#endif diff --git a/text.c b/text.c index 25ce1ed..c41fe3e 100644 --- a/text.c +++ b/text.c @@ -897,6 +897,10 @@ bool text_iterator_char_prev(Iterator *it, char *c) { return false; } +bool text_byte_get(Text *ed, size_t pos, char *buf) { + return text_bytes_get(ed, pos, 1, buf); +} + size_t text_bytes_get(Text *ed, size_t pos, size_t len, char *buf) { if (!buf) return 0; diff --git a/text.h b/text.h index 62800b8..9d4fa34 100644 --- a/text.h +++ b/text.h @@ -1,4 +1,12 @@ +#ifndef TEXT_H +#define TEXT_H + #include +#include + +typedef struct { + size_t start, end; /* range in bytes from start of file */ +} Filerange; typedef struct Text Text; typedef struct Piece Piece; @@ -28,6 +36,7 @@ bool text_redo(Text*); size_t text_pos_by_lineno(Text*, size_t lineno); size_t text_lineno_by_pos(Text*, size_t pos); +bool text_byte_get(Text *ed, size_t pos, char *buf); size_t text_bytes_get(Text*, size_t pos, size_t len, char *buf); Iterator text_iterator_get(Text*, size_t pos); @@ -68,3 +77,5 @@ int text_search_backward(Text*, size_t pos, size_t len, Regex *r, size_t nmatch, // TMP void text_debug(Text *ed); + +#endif -- cgit v1.2.3