From 04b8bd9a7e81cc8afbe51a094bb3d0ad3cae8347 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 2 Apr 2018 15:05:54 -0400 Subject: [PATCH] initial rework buffer api. basically just segfaults. still investigating --- inc/edit.h | 7 +- lib/buf.c | 249 +++++++++++++++++++++-------------------------------- lib/view.c | 82 +++--------------- tide.c | 36 -------- 4 files changed, 112 insertions(+), 262 deletions(-) diff --git a/inc/edit.h b/inc/edit.h index d43f3c2..9782371 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -53,11 +53,8 @@ void buf_init(Buf* buf); size_t buf_load(Buf* buf, char* path); void buf_reload(Buf* buf); void buf_save(Buf* buf); -Rune buf_get(Buf* buf, size_t pos); size_t buf_end(Buf* buf); -size_t buf_insert(Buf* buf, bool indent, size_t off, Rune rune); -size_t buf_delete(Buf* buf, size_t beg, size_t end); -size_t buf_change(Buf* buf, size_t beg, size_t end); + void buf_chomp(Buf* buf); void buf_undo(Buf* buf, Sel* sel); void buf_redo(Buf* buf, Sel* sel); @@ -82,6 +79,7 @@ size_t buf_getln(Buf* buf, size_t off); size_t buf_getcol(Buf* buf, size_t pos); size_t buf_setcol(Buf* buf, size_t pos, size_t col); +int buf_getrat(Buf* buf, size_t off); void buf_putc(Buf* buf, int c, Sel* sel); void buf_puts(Buf* buf, char* s, Sel* sel); int buf_getc(Buf* buf, Sel* sel); @@ -147,7 +145,6 @@ void view_selctx(View* view); void view_scroll(View* view, int move); void view_scrollpage(View* view, int move); void view_setln(View* view, size_t line); -void view_indent(View* view, int dir); size_t view_selsize(View* view); void view_selprev(View* view); void view_setcursor(View* view, size_t row, size_t col, bool extsel); diff --git a/lib/buf.c b/lib/buf.c index d6de51a..2b0e2e7 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -86,7 +86,7 @@ void buf_save(Buf* buf) { /* text files should always end in a new line. If we detected a binary file or at least a non-utf8 file, skip this part. */ if (!buf_iseol(buf, buf_end(buf)-1)) - buf_insert(buf, false, buf_end(buf), '\n'); + buf_putc(buf, '\n', &(Sel){ .end = buf_end(buf)-1 }); char* wptr; long fd, nwrite, towrite; @@ -110,8 +110,37 @@ void buf_save(Buf* buf) { } } -Rune buf_get(Buf* buf, size_t off) { - if (off >= buf_end(buf)) return (Rune)'\n'; +size_t buf_end(Buf* buf) { + size_t bufsz = buf->bufend - buf->bufstart; + size_t gapsz = buf->gapend - buf->gapstart; + return (bufsz - gapsz); +} + +/******************************************************************************/ + +static Sel getsel(Buf* buf, Sel* p_sel) { + size_t temp; + Sel sel = (p_sel ? *p_sel : buf->selection); + if (sel.end < sel.beg) + temp = sel.beg, sel.beg = sel.end, sel.end = temp; + return sel; +} + +static void setsel(Buf* buf, Sel* p_sel, Sel* p_newsel) { + if (p_sel) + *p_sel = *p_newsel; + else + buf->selection = *p_newsel; +} + +static void putb(Buf* buf, char b, Sel* p_sel) { + syncgap(buf, p_sel->end); + *(buf->gapstart++) = b; + p_sel->end = p_sel->end + 1u; + p_sel->beg = p_sel->end; +} + +static char getb(Buf* buf, size_t off) { size_t bsz = (buf->gapstart - buf->bufstart); if (off < bsz) return *(buf->bufstart + off); @@ -119,69 +148,59 @@ Rune buf_get(Buf* buf, size_t off) { return *(buf->gapend + (off - bsz)); } -size_t buf_end(Buf* buf) { - size_t bufsz = buf->bufend - buf->bufstart; - size_t gapsz = buf->gapend - buf->gapstart; - return (bufsz - gapsz); +int buf_getrat(Buf* buf, size_t off) { + size_t rlen = 0; + Rune rune = 0; + while (!utf8decode(&rune, &rlen, getb(buf, off++))); + return rune; } -size_t buf_insert(Buf* buf, bool fmt, size_t off, Rune rune) { - bool is_eol = (rune == '\n'); - buf->modified = true; - if (fmt && ExpandTabs && rune == '\t') { - size_t tabwidth = TabWidth; - size_t n = (tabwidth - ((off - buf_bol(buf, off)) % tabwidth)); - log_insert(buf, &(buf->undo), off, off+n); - for(; n > 0; n--) off += insert(buf, off, ' '); - } else { - size_t n = insert(buf, off, rune); - if (n > 0) { - log_insert(buf, &(buf->undo), off, off+n); - off += n; - } - } - if (fmt && CopyIndent && is_eol) { - size_t beg = buf_bol(buf, off-1), end = beg; - for (; end < buf_end(buf) && (' ' == buf_get(buf, end) || '\t' == buf_get(buf, end)); end++); - for (; beg < end; beg++) - off = buf_insert(buf, true, off, buf_get(buf, beg)); - } - log_clear(&(buf->redo)); - return off; +void buf_putc(Buf* buf, int c, Sel* p_sel) { + char utf8buf[UTF_MAX+1] = {0}; + (void)utf8encode(utf8buf, c); + buf_puts(buf, utf8buf, p_sel); } -size_t buf_delete(Buf* buf, size_t beg, size_t end) { - buf->modified = true; - log_clear(&(buf->redo)); - for (size_t i = end-beg; i > 0; i--) { - char c = buf_get(buf, beg); - log_delete(buf, &(buf->undo), beg, &c, 1); - delete(buf, beg); +void buf_puts(Buf* buf, char* s, Sel* p_sel) { + buf_del(buf, p_sel); + Sel sel = getsel(buf, p_sel); + while (s && *s) putb(buf, *(s++), &sel); + setsel(buf, p_sel, &sel); +} + +int buf_getc(Buf* buf, Sel* p_sel) { + Sel sel = getsel(buf, p_sel); + return buf_getrat(buf, sel.end); +} + +char* buf_gets(Buf* buf, Sel* p_sel) { + Sel sel = getsel(buf, p_sel); + size_t nbytes = sel.end - sel.beg; + char* str = malloc(nbytes+1); + for (size_t i = 0; i < nbytes; i++) + str[i] = getb(buf, sel.beg + i); + str[nbytes] = '\0'; + return str; +} + +void buf_del(Buf* buf, Sel* p_sel) { + Sel sel = getsel(buf, p_sel); + size_t nbytes = sel.end - sel.beg; + if (nbytes > 0) { + //char* str = buf_gets(buf, &sel); + syncgap(buf, sel.beg); + buf->gapend += nbytes; + // update log here + // free(str); } - return beg; -} - -size_t buf_change(Buf* buf, size_t beg, size_t end) { - /* delete the range first */ - size_t off = buf_delete(buf, beg, end); - /* now create a new insert item of length 0 with the same transaction id as - the delete. This will cause subsequent inserts to be coalesced into the - same transaction */ - Log* dellog = buf->undo; - Log* inslog = (Log*)calloc(sizeof(Log), 1); - inslog->transid = (dellog ? dellog->transid : buf->transid); - inslog->insert = true; - inslog->data.ins.beg = beg; - inslog->data.ins.end = beg; - inslog->next = dellog; - buf->undo = inslog; - return off; } +/******************************************************************************/ + void buf_chomp(Buf* buf) { size_t end = buf_end(buf); if (!end) return; - Rune r = buf_get(buf, end-1); + Rune r = buf_getrat(buf, end-1); if (r == '\n') { delete(buf, end-1); if (buf->undo->insert && buf->undo->data.ins.end == end) @@ -215,7 +234,7 @@ void buf_logclear(Buf* buf) { } bool buf_iseol(Buf* buf, size_t off) { - Rune r = buf_get(buf, off); + Rune r = buf_getrat(buf, off); return (r == '\n'); } @@ -230,31 +249,31 @@ size_t buf_eol(Buf* buf, size_t off) { } size_t buf_bow(Buf* buf, size_t off) { - for (; risword(buf_get(buf, off-1)); off--); + for (; risword(buf_getrat(buf, off-1)); off--); return off; } size_t buf_eow(Buf* buf, size_t off) { - for (; risword(buf_get(buf, off)); off++); + for (; risword(buf_getrat(buf, off)); off++); return off-1; } size_t buf_lscan(Buf* buf, size_t pos, Rune r) { size_t off = pos; - for (; (off > 0) && (r != buf_get(buf, off)); off--); - return (buf_get(buf, off) == r ? off : pos); + for (; (off > 0) && (r != buf_getrat(buf, off)); off--); + return (buf_getrat(buf, off) == r ? off : pos); } size_t buf_rscan(Buf* buf, size_t pos, Rune r) { size_t off = pos; size_t end = buf_end(buf); - for (; (off < end) && (r != buf_get(buf, off)); off++); - return (buf_get(buf, off) == r ? off : pos); + for (; (off < end) && (r != buf_getrat(buf, off)); off++); + return (buf_getrat(buf, off) == r ? off : pos); } void buf_getword(Buf* buf, bool (*isword)(Rune), Sel* sel) { - for (; isword(buf_get(buf, sel->beg-1)); sel->beg--); - for (; isword(buf_get(buf, sel->end)); sel->end++); + for (; isword(buf_getrat(buf, sel->beg-1)); sel->beg--); + for (; isword(buf_getrat(buf, sel->end)); sel->end++); sel->end--; } @@ -263,18 +282,18 @@ void buf_getblock(Buf* buf, Rune first, Rune last, Sel* sel) { size_t beg, end = sel->end; /* figure out which end of the block we're starting at */ - if (buf_get(buf, end) == first) + if (buf_getrat(buf, end) == first) dir = +1, balance++, beg = end++; - else if (buf_get(buf, end) == last) + else if (buf_getrat(buf, end) == last) dir = -1, balance--, beg = end--; else return; /* scan for a blanced set of braces */ while (true) { - if (buf_get(buf, end) == first) + if (buf_getrat(buf, end) == first) balance++; - else if (buf_get(buf, end) == last) + else if (buf_getrat(buf, end) == last) balance--; if (balance == 0 || end >= buf_end(buf) || end == 0) @@ -344,8 +363,8 @@ void buf_findstr(Buf* buf, int dir, char* str, size_t* beg, size_t* end) { size_t rlen = rstrlen(runes); size_t start = *beg, mbeg = start+dir, mend = mbeg + rlen; while (mbeg != start) { - if ((buf_get(buf, mbeg) == runes[0]) && - (buf_get(buf, mend-1) == runes[rlen-1]) && + if ((buf_getrat(buf, mbeg) == runes[0]) && + (buf_getrat(buf, mend-1) == runes[rlen-1]) && (0 == rune_match(buf, mbeg, mend, runes))) { *beg = mbeg; @@ -406,7 +425,7 @@ size_t buf_getcol(Buf* buf, size_t pos) { size_t curr = buf_bol(buf, pos); size_t col = 0; for (; curr < pos; curr = buf_byrune(buf, curr, 1)) - col += runewidth(col, buf_get(buf, curr)); + col += runewidth(col, buf_getrat(buf, curr)); return col; } @@ -417,11 +436,11 @@ size_t buf_setcol(Buf* buf, size_t pos, size_t col) { size_t i = 0; /* determine the length of the line in columns */ for (; !buf_iseol(buf, curr); curr++) - len += runewidth(len, buf_get(buf, curr)); + len += runewidth(len, buf_getrat(buf, curr)); /* iterate over the runes until we reach the target column */ curr = bol, i = 0; while (i < col && i < len) { - int width = runewidth(i, buf_get(buf, curr)); + int width = runewidth(i, buf_getrat(buf, curr)); curr = buf_byrune(buf, curr, 1); if (col >= i && col < (i+width)) break; @@ -534,7 +553,7 @@ static size_t insert(Buf* buf, size_t off, Rune rune) { static int rune_match(Buf* buf, size_t mbeg, size_t mend, Rune* runes) { for (; *runes; runes++, mbeg++) { - int cmp = *runes - buf_get(buf, mbeg); + int cmp = *runes - buf_getrat(buf, mbeg); if (cmp != 0) return cmp; } return 0; @@ -556,7 +575,7 @@ static void swaplog(Buf* buf, Log** from, Log** to, Sel* sel) { newlog->data.del.len = n; newlog->data.del.runes = (char*)malloc(n); for (size_t i = 0; i < n; i++) { - newlog->data.del.runes[i] = buf_get(buf, log->data.ins.beg); + newlog->data.del.runes[i] = buf_getrat(buf, log->data.ins.beg); delete(buf, log->data.ins.beg); } } else { @@ -576,83 +595,9 @@ static Rune nextrune(Buf* buf, size_t off, int move, bool (*testfn)(Rune)) { bool ret = false; size_t end = buf_end(buf); if (move < 0 && off > 0) - ret = testfn(buf_get(buf, off-1)); + ret = testfn(buf_getrat(buf, off-1)); else if (move > 0 && off < end) - ret = testfn(buf_get(buf, off+1)); + ret = testfn(buf_getrat(buf, off+1)); return ret; } -/******************************************************************************/ - -static Sel getsel(Buf* buf, Sel* p_sel) { - size_t temp; - Sel sel = (p_sel ? *p_sel : buf->selection); - if (sel.end < sel.beg) - temp = sel.beg, sel.beg = sel.end, sel.end = temp; - return sel; -} - -static void setsel(Buf* buf, Sel* p_sel, Sel* p_newsel) { - if (p_sel) - *p_sel = *p_newsel; - else - buf->selection = *p_newsel; -} - -static void putb(Buf* buf, char b, Sel* p_sel) { - syncgap(buf, p_sel->end); - *(buf->gapstart++) = b; - p_sel->end = p_sel->end + 1u; - p_sel->beg = p_sel->end; -} - -static char getb(Buf* buf, size_t off) { - size_t bsz = (buf->gapstart - buf->bufstart); - if (off < bsz) - return *(buf->bufstart + off); - else - return *(buf->gapend + (off - bsz)); -} - -void buf_putc(Buf* buf, int c, Sel* p_sel) { - char utf8buf[UTF_MAX+1] = {0}; - (void)utf8encode(utf8buf, c); - buf_puts(buf, utf8buf, p_sel); -} - -void buf_puts(Buf* buf, char* s, Sel* p_sel) { - buf_del(buf, p_sel); - Sel sel = getsel(buf, p_sel); - while (s && *s) putb(buf, *(s++), &sel); - setsel(buf, p_sel, &sel); -} - -int buf_getc(Buf* buf, Sel* p_sel) { - Sel sel = getsel(buf, p_sel); - size_t rlen = 0; - Rune rune = 0; - while (!utf8decode(&rune, &rlen, getb(buf, sel.end++))); - return rune; -} - -char* buf_gets(Buf* buf, Sel* p_sel) { - Sel sel = getsel(buf, p_sel); - size_t nbytes = sel.end - sel.beg; - char* str = malloc(nbytes+1); - for (size_t i = 0; i < nbytes; i++) - str[i] = getb(buf, sel.beg + i); - str[nbytes] = '\0'; - return str; -} - -void buf_del(Buf* buf, Sel* p_sel) { - Sel sel = getsel(buf, p_sel); - size_t nbytes = sel.end - sel.beg; - if (nbytes > 0) { - //char* str = buf_gets(buf, &sel); - syncgap(buf, sel.beg); - buf->gapend += nbytes; - // update log here - // free(str); - } -} diff --git a/lib/view.c b/lib/view.c index f8127cd..2555e10 100644 --- a/lib/view.c +++ b/lib/view.c @@ -57,7 +57,7 @@ void view_reload(View* view) { size_t view_limitrows(View* view, size_t maxrows, size_t ncols) { size_t nrows = 1, pos = 0, col = 0; while (nrows < maxrows && pos < buf_end(&(view->buffer))) { - Rune r = buf_get(&(view->buffer), pos++); + Rune r = buf_getrat(&(view->buffer), pos++); col += runewidth(col, r); if (col >= ncols || r == '\n') col = 0, nrows++; @@ -186,14 +186,8 @@ void view_insert(View* view, bool indent, Rune rune) { /* ignore non-printable control characters */ if (!isspace(rune) && (rune >= 0 && rune < 0x20)) return; - if (num_selected(view->selection)) { - Sel sel = view->selection; - selswap(&sel); - sel.beg = sel.end = buf_change(&(view->buffer), sel.beg, sel.end); - view->selection = sel; - } - unsigned newpos = buf_insert(&(view->buffer), indent, view->selection.end, rune); - move_to(view, false, newpos); + buf_putc(&(view->buffer), rune, &(view->selection)); + move_to(view, false, view->selection.end); } void view_delete(View* view, int dir, bool byword) { @@ -201,8 +195,8 @@ void view_delete(View* view, int dir, bool byword) { if (sel->beg == sel->end) (byword ? view_byword : view_byrune)(view, dir, true); selswap(sel); - unsigned newpos = buf_delete(&(view->buffer), sel->beg, sel->end); - move_to(view, false, newpos); + buf_del(&(view->buffer), sel); + move_to(view, false, sel->beg); } void view_jumpto(View* view, bool extsel, size_t off) { @@ -214,7 +208,7 @@ void view_bol(View* view, bool extsel) { Buf* buf = &(view->buffer); unsigned bol = buf_bol(buf, view->selection.end); unsigned boi = bol; - for (; ' ' == buf_get(buf, boi) || '\t' == buf_get(buf, boi); boi++); + for (; ' ' == buf_getrat(buf, boi) || '\t' == buf_getrat(buf, boi); boi++); unsigned pos = view->selection.end; pos = (pos == bol || pos > boi ? boi : bol); move_to(view, extsel, pos); @@ -269,7 +263,7 @@ void view_append(View* view, char* str) { if (view->selection.end != end) view->selection = (Sel){ .beg = end, .end = end }; if (!num_selected(view->selection) && !buf_iseol(&(view->buffer), view->selection.end-1)) { - buf_insert(&(view->buffer), false, view->selection.end++, '\n'); + buf_putc(&(view->buffer), '\n', &(view->selection)); view->selection.beg++; } unsigned beg = view->selection.beg; @@ -278,24 +272,7 @@ void view_append(View* view, char* str) { } char* view_getstr(View* view, Sel* range) { - Buf* buf = &(view->buffer); - Sel sel = (range ? *range : view->selection); - selswap(&sel); - char utf[UTF_MAX] = {0}; - size_t len = 0; - char* str = NULL; - for (; sel.beg < sel.end; sel.beg++) { - Rune rune = buf_get(buf, sel.beg); - size_t n = utf8encode(utf, rune); - str = realloc(str, len + n); - memcpy(str+len, utf, n); - len += n; - } - if (str) { - str = realloc(str, len+1); - str[len] = '\0'; - } - return str; + return buf_gets(&(view->buffer), &(view->selection)); } char* view_getcmd(View* view) { @@ -331,41 +308,8 @@ void view_scrollpage(View* view, int move) { view_scroll(view, move); } -void view_indent(View* view, int dir) { - Buf* buf = &(view->buffer); - unsigned indoff = (ExpandTabs ? TabWidth : 1); - selswap(&(view->selection)); - view->selection.beg = buf_bol(buf, view->selection.beg); - view->selection.end = buf_eol(buf, view->selection.end); - unsigned off = buf_bol(buf, view->selection.end); - if (num_selected(view->selection) == 0) return; - - do { - if (dir == RIGHT) { - buf_insert(buf, true, off, '\t'); - view->selection.end += indoff; - } else if (dir == LEFT) { - unsigned i = 4; - for (; i > 0; i--) { - if (' ' == buf_get(buf, off)) { - buf_delete(buf, off, off+1); - view->selection.end--; - } else { - break; - } - } - if (i && '\t' == buf_get(buf, off)) { - buf_delete(buf, off, off+1); - view->selection.end--; - } - } - off = buf_byline(buf, off, UP); - - } while (off && off >= view->selection.beg); -} - Rune view_getrune(View* view) { - return buf_get(&(view->buffer), view->selection.end); + return buf_getc(&(view->buffer), &(view->selection)); } void view_scrollto(View* view, size_t csr) { @@ -414,7 +358,7 @@ static void move_to(View* view, bool extsel, size_t off) { static void select_context(View* view, bool (*isword)(Rune), Sel* sel) { Buf* buf = &(view->buffer); size_t bol = buf_bol(buf, sel->end); - Rune r = buf_get(buf, sel->end); + Rune r = buf_getc(buf, sel); if (r == '(' || r == ')') { buf_getblock(buf, '(', ')', sel); } else if (r == '[' || r == ']') { @@ -472,7 +416,7 @@ static void find_cursor(View* view, size_t* csrx, size_t* csry) { *csry = y, *csrx = x; break; } - x += runewidth(x, buf_get(&(view->buffer),pos++)); + x += runewidth(x, buf_getrat(&(view->buffer), pos++)); } break; } @@ -514,7 +458,7 @@ static size_t fill_row(View* view, unsigned row, size_t pos) { clearrow(view, row); for (size_t x = 0; x < view->ncols;) { uint32_t attr = (in_selection(view->selection, pos) ? view->clrsel : view->clrnor); - Rune r = buf_get(&(view->buffer), pos++); + Rune r = buf_getrat(&(view->buffer), pos++); x += setcell(view, row, x, attr, r); if (buf_iseol(&(view->buffer), pos-1)) { break; @@ -528,7 +472,7 @@ static unsigned prev_screen_line(View* view, unsigned bol, unsigned off) { while (true) { unsigned x; for (x = 0; x < view->ncols && (pos + x) < off; x++) - x += runewidth(x, buf_get(&(view->buffer), pos+x)); + x += runewidth(x, buf_getrat(&(view->buffer), pos+x)); if ((pos + x) >= off) break; pos += x; } diff --git a/tide.c b/tide.c index 376f0ae..f732aa3 100644 --- a/tide.c +++ b/tide.c @@ -279,35 +279,11 @@ void exec(char* cmd) { /* Action Callbacks ******************************************************************************/ -static void trim_whitespace(char* arg) { - Buf* buf = win_buf(EDIT); - if (TrimOnSave && buf_end(buf) > 0) { - View* view = win_view(EDIT); - unsigned off = 0, prev = 1; - /* loop through the buffer till we hit the end or we stop advancing */ - while (off < buf_end(buf) && prev != off) { - off = buf_eol(buf, off); - Rune r = buf_get(buf, off-1); - for (; (r == ' ' || r == '\t'); r = buf_get(buf, off-1)) { - if (off <= view->selection.beg) { - view->selection.end--; - view->selection.beg--; - } - off = buf_delete(buf, off-1, off); - } - /* make sure we keep advancing */ - prev = off; - off = buf_byline(buf, off, +1); - } - } -} - static void quit(char* arg) { win_quit(); } static void put(char* arg) { - trim_whitespace(arg); win_save(arg); } @@ -400,14 +376,6 @@ static void indent(char* arg) { CopyIndent = !CopyIndent; } -static void del_indent(char* arg) { - view_indent(win_view(FOCUSED), LEFT); -} - -static void add_indent(char* arg) { - view_indent(win_view(FOCUSED), RIGHT); -} - static void eol_mode(char* arg) { DosLineFeed = !DosLineFeed; cmd_exec(DosLineFeed ? CMD_TO_DOS : CMD_TO_UNIX); @@ -483,10 +451,6 @@ static KeyBinding Bindings[] = { { ModCtrl, 'l', select_line }, { ModCtrl|ModShift, 'a', select_all }, - /* Block Indent */ - { ModCtrl, '[', del_indent }, - { ModCtrl, ']', add_indent }, - /* Common Special Keys */ { ModNone, KEY_PGUP, page_up }, { ModNone, KEY_PGDN, page_dn }, -- 2.51.0