{
return;
}
+
if (b == '\n' && DosLineFeed)
{
putb(buf, '\r', p_sel);
}
}
-void buf_init(Buf* buf) {
+void buf_init(Buf* buf)
+{
+ require(buf != NULL);
+
/* cleanup old data if there is any */
- if (buf->bufstart) {
+ if (buf->bufstart)
+ {
free(buf->bufstart);
buf->bufstart = NULL;
free(buf->path);
buf->redo = NULL;
buf->transid = -1;
buf->selection = (Sel){0,0,0};
+
ensure(buf_valid(buf));
}
-void buf_setpath(Buf* buf, char* path) {
- if (path) {
+void buf_setpath(Buf* buf, char* path)
+{
+ require(buf != NULL);
+ if (path)
+ {
free(buf->path);
buf->path = strdup(path);
ensure(buf->path != NULL);
}
}
-void buf_load(Buf* buf, char* path) {
- if (!path) return;
+void buf_load(Buf* buf, char* path)
+{
+ if (!path)
+ {
+ return;
+ }
+
/* process the file path and address */
if (path[0] == '.' && path[1] == '/')
+ {
path += 2;
+ }
buf->path = strdup(path);
/* load the contents from the file */
int fd, nread;
struct stat sb = {0};
- if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) {
+ if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0))
+ {
/* allocate the buffer in advance */
free(buf->bufstart);
buf->bufsize = pagealign(sb.st_size);
while (sb.st_size && (nread = read(fd, buf->gapstart, sb.st_size)) > 0)
buf->gapstart += nread, sb.st_size -= nread;
}
- if (fd > 0) close(fd);
+ if (fd > 0)
+ {
+ close(fd);
+ }
/* reset buffer state */
buf->status = NORMAL;
ensure(buf_valid(buf));
}
-void buf_reload(Buf* buf) {
+void buf_reload(Buf* buf)
+{
char* path = buf->path;
buf->path = NULL;
buf_init(buf);
buf_load(buf, path);
}
-static void trim_whitespace(Buf* buf) {
- if (!TrimOnSave || !buf_end(buf)) return;
+static void trim_whitespace(Buf* buf)
+{
+ if (!TrimOnSave || !buf_end(buf))
+ {
+ return;
+ }
Sel sel = buf->selection;
bool swapped = (sel.beg > sel.end);
- if (swapped) sel = selswap(sel);
+ if (swapped)
+ {
+ sel = selswap(sel);
+ }
+
unsigned prev = 1;
buf->selection.beg = buf->selection.end = 0;
buf_logstart(buf);
- while (prev != buf->selection.end) {
+ while (prev != buf->selection.end)
+ {
int r = getb(buf, buf->selection.end);
/* If we reached a newline, then delete whatever we have selected */
- if (r == '\r' || r == '\n') {
+ if (r == '\r' || r == '\n')
+ {
buf->selection.beg = buf_byrune(buf, buf->selection.beg, +1);
Sel del = buf->selection;
sel.beg -= (del.beg < sel.beg ? (min(del.end, sel.beg) - del.beg) : 0);
/* if current char is not whitespace, then shrink the selection */
if (r != ' ' && r != '\t')
+ {
buf->selection.beg = buf->selection.end;
+ }
/* move to the next character */
prev = buf->selection.end;
buf->selection.end = buf_byrune(buf, buf->selection.end, +1);
}
buf_logstop(buf);
- if (swapped) sel = selswap(sel);
+ if (swapped)
+ {
+ sel = selswap(sel);
+ }
buf->selection = sel;
}
-int buf_save(Buf* buf, char* path) {
+int buf_save(Buf* buf, char* path)
+{
buf_setpath(buf, path);
- if (0 == buf_end(buf)) return buf->status;
+ if (0 == buf_end(buf))
+ {
+ return buf->status;
+ }
trim_whitespace(buf);
char* wptr;
long fd, nwrite = 0, towrite = 0;
- if (buf->path && (fd = open(buf->path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0) {
+ if (buf->path && (fd = open(buf->path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0)
+ {
/* write the chunk before the gap */
wptr = buf->bufstart, towrite = (buf->gapstart - buf->bufstart);
while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
close(fd);
/* report success or failure */
buf->status = (nwrite >= 0 ? NORMAL : ERRORED);
- } else {
+ }
+ else
+ {
buf->status = ERRORED;
}
+
if (buf->status == NORMAL)
+ {
buf->save = buf->undo;
+ }
ensure(buf_valid(buf));
return buf->status;
/* Undo/Redo Operations
******************************************************************************/
-static Log* mklog(Buf* buf, size_t beg, size_t end, char* data, Log* next) {
+static Log* mklog(Buf* buf, size_t beg, size_t end, char* data, Log* next)
+{
Log* log = calloc(1, sizeof(Log));
log->transid = (buf->transid < 0 ? 0 : buf->transid);
log->beg = beg;
return log;
}
-static void log_clear(Log** list) {
- while (*list) {
+static void log_clear(Log** list)
+{
+ while (*list)
+ {
Log* deadite = *list;
*list = (*list)->next;
if (deadite->data)
+ {
free(deadite->data);
+ }
free(deadite);
}
}
-static void dumplog(Buf* buf) {
+static void dumplog(Buf* buf)
+{
#if 0
printf("\nUndo:\n");
for (Log* log = buf->undo; log; log = log->next)
+ {
printf(" (%d) %lu-%lu '%s'\n", log->transid, log->beg, log->end, log->data);
+ }
printf("Redo:\n");
for (Log* log = buf->redo; log; log = log->next)
+ {
printf(" (%d) %lu-%lu '%s'\n", log->transid, log->beg, log->end, log->data);
+ }
#else
(void)buf;
#endif
}
-static void log_add(Buf* buf, size_t beg, size_t end, char* data) {
+static void log_add(Buf* buf, size_t beg, size_t end, char* data)
+{
Log* prev = buf->undo;
log_clear(&(buf->redo));
+
/* decide if this is an insert or delete */
- if (!prev || (buf->transid > 0 && buf->transid != prev->transid)) {
+ if (!prev || (buf->transid > 0 && buf->transid != prev->transid))
+ {
buf->undo = mklog(buf, beg, end, data, prev);
- } else if (!data && !prev->data && prev->end == beg) {
+ }
+ else if (!data && !prev->data && prev->end == beg)
+ {
prev->end = end;
- } else if (prev->data && data && prev->beg == beg) {
+ }
+ else if (prev->data && data && prev->beg == beg)
+ {
char* newdata = strmcat(prev->data, data, 0);
free(data);
free(prev->data);
prev->data = newdata;
- } else if (prev->data && data && prev->beg == beg+1) {
+ }
+ else if (prev->data && data && prev->beg == beg+1)
+ {
char* newdata = strmcat(data, prev->data, 0);
free(data);
free(prev->data);
prev->data = newdata;
prev->end = --prev->beg;
- } else {
+ }
+ else
+ {
buf->undo = mklog(buf, beg, end, data, prev);
}
+
dumplog(buf);
}
-static void log_swap(Buf* buf, Log** src, Log** dest) {
- if (!*src) return;
+static void log_swap(Buf* buf, Log** src, Log** dest)
+{
+ if (!*src)
+ {
+ return;
+ }
+
Log* item = *src;
*src = item->next;
buf->selection.beg = item->beg;
buf->selection.end = item->end;
- if (item->data) {
+ if (item->data)
+ {
/* reinsert deleted bytes */
for (char* s = item->data; s && *s; s++, item->end++)
+ {
putb(buf, *s, &(buf->selection));
+ }
free(item->data);
item->data = NULL;
buf->selection.beg = item->beg;
buf->selection.end = item->end;
- } else {
+ }
+ else
+ {
/* delete the added bytes */
Sel sel = selget(buf);
item->data = buf_gets(buf);
item->beg = sel.beg;
item->end = sel.end;
}
+
/* push item onto destination stack */
item->next = *dest;
*dest = item;
/* undo recursively if this is part of a transaction */
if (*src && item->transid && item->transid == (*src)->transid)
+ {
log_swap(buf, src, dest);
+ }
else
+ {
dumplog(buf);
+ }
+
if (buf->save == buf->undo)
+ {
buf->status = NORMAL;
+ }
}
-void buf_logstart(Buf* buf) {
+void buf_logstart(Buf* buf)
+{
buf->transid = abs(buf->transid);
}
-void buf_logstop(Buf* buf) {
+void buf_logstop(Buf* buf)
+{
if (buf->transid > 0)
+ {
buf->transid = -(buf->transid + 1);
+ }
}
-void buf_undo(Buf* buf) {
+void buf_undo(Buf* buf)
+{
log_swap(buf, &(buf->undo), &(buf->redo));
ensure(buf_valid(buf));
}
-void buf_redo(Buf* buf) {
+void buf_redo(Buf* buf)
+{
log_swap(buf, &(buf->redo), &(buf->undo));
ensure(buf_valid(buf));
}
-void buf_logclear(Buf* buf) {
+void buf_logclear(Buf* buf)
+{
log_clear(&(buf->redo));
log_clear(&(buf->undo));
}
-void buf_lastins(Buf* buf) {
+void buf_lastins(Buf* buf)
+{
Log* log = buf->undo;
- if (!log) return;
+ if (!log)
+ {
+ return;
+ }
Sel sel = {.beg = log->beg, .end = log->end };
size_t delsize = 0;
int transid = log->transid;
+
/* try and expand the selected region to encompass related inserts */
- for (; log && (log->transid == transid); log = log->next) {
- if (!log->data) {
+ for (; log && (log->transid == transid); log = log->next)
+ {
+ if (!log->data)
+ {
size_t ibeg = log->beg, iend = log->end - delsize;
- if (iend < ibeg || ibeg > sel.beg || iend < sel.beg) break;
- if (ibeg < sel.beg && iend > sel.end) break;
+ if (iend < ibeg || ibeg > sel.beg || iend < sel.beg)
+ {
+ break;
+ }
+ if (ibeg < sel.beg && iend > sel.end)
+ {
+ break;
+ }
sel.beg = ibeg, delsize = 0;
- } else {
+ }
+ else
+ {
/* bail if the delete doesnt overlap */
- if(log->beg != sel.beg) break;
+ if (log->beg != sel.beg)
+ {
+ break;
+ }
delsize = strlen(log->data);
}
}
/* Basic Operations and Accessors
******************************************************************************/
-size_t buf_end(Buf* buf) {
+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) {
+int buf_getrat(Buf* buf, size_t off)
+{
size_t rlen = 0;
Rune rune = 0;
if (getb(buf, off) == '\r' && getb(buf, off+1) == '\n')
+ {
rune = '\n';
+ }
else
- while (!utf8decode(&rune, &rlen, getb(buf, off++)));
+ {
+ while ( !utf8decode(&rune, &rlen, getb(buf, off++)) )
+ {
+ }
+ }
return rune;
}
-void buf_putc(Buf* buf, int c) {
+void buf_putc(Buf* buf, int c)
+{
char utf8buf[UTF_MAX+1] = {0};
(void)utf8encode(utf8buf, c);
buf_puts(buf, utf8buf);
ensure(buf_valid(buf));
}
-void buf_puts(Buf* buf, char* s) {
+void buf_puts(Buf* buf, char* s)
+{
buf_del(buf);
size_t beg = buf_selbeg(buf);
- if (s && *s) {
- while (*s) putch(buf, *(s++), &(buf->selection));
+ if (s && *s)
+ {
+ while (*s)
+ {
+ putch(buf, *(s++), &(buf->selection));
+ }
log_add(buf, beg, buf_selend(buf), NULL);
}
ensure(buf_valid(buf));
}
-int buf_getc(Buf* buf) {
+int buf_getc(Buf* buf)
+{
return buf_getrat(buf, buf->selection.end);
}
-char* buf_gets(Buf* buf) {
+char* buf_gets(Buf* buf)
+{
Sel sel = selget(buf);
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;
}
-char* buf_getsat(Buf* buf, size_t beg, size_t end) {
+char* buf_getsat(Buf* buf, size_t beg, size_t end)
+{
Sel sel = selget(buf);
buf->selection = (Sel){ .beg = beg, .end = end };
char* str = buf_gets(buf);
return str;
}
-void buf_del(Buf* buf) {
+void buf_del(Buf* buf)
+{
Sel sel = selget(buf);
size_t nbytes = sel.end - sel.beg;
- if (nbytes > 0) {
+ if (nbytes > 0)
+ {
buf->status = MODIFIED;
char* str = buf_gets(buf);
buf_syncgap(buf, sel.beg);
/* Positional and Movement Operations
******************************************************************************/
-static Rune nextrune(Buf* buf, size_t off, int move, bool (*testfn)(Rune)) {
+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_getrat(buf, off-1));
+ }
else if (move > 0 && off < end)
+ {
ret = testfn(buf_getrat(buf, off+1));
+ }
return ret;
}
-static void selline(Buf* buf) {
+static void selline(Buf* buf)
+{
Sel sel = selget(buf);
sel.beg = buf_bol(buf, sel.end);
sel.end = buf_eol(buf, sel.end);
buf->selection = sel;
}
-static void selblock(Buf* buf, Rune first, Rune last) {
+static void selblock(Buf* buf, Rune first, Rune last)
+{
Sel sel = selget(buf);
int balance = 0, dir;
size_t beg, end = sel.end;
/* figure out which end of the block we're starting at */
if (buf_getrat(buf, end) == first)
+ {
dir = +1, balance++, beg = end++;
+ }
else if (buf_getrat(buf, end) == last)
+ {
dir = -1, balance--, beg = end--;
+ }
else
+ {
return;
+ }
/* scan for a blanced set of braces */
- while (true) {
+ while (true)
+ {
if (buf_getrat(buf, end) == first)
+ {
balance++;
+ }
else if (buf_getrat(buf, end) == last)
+ {
balance--;
+ }
if (balance == 0 || end >= buf_end(buf) || end == 0)
+ {
break;
+ }
else
+ {
end += dir;
+ }
}
/* bail if we failed to find a block */
- if (balance != 0) return;
+ if (balance != 0)
+ {
+ return;
+ }
/* update the passed in selection */
- if (end > beg) beg++; else end++;
- buf->selection.beg = beg, buf->selection.end = end;
+ if (end > beg)
+ {
+ beg++;
+ }
+ else
+ {
+ end++;
+ }
+ buf->selection.beg = beg;
+ buf->selection.end = end;
}
-static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str) {
- for (; *str && mbeg < mend; str++, mbeg++) {
+static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str)
+{
+ for (; *str && mbeg < mend; str++, mbeg++)
+ {
int cmp = *str - getb(buf, mbeg);
- if (cmp != 0) return cmp;
+ if (cmp != 0)
+ {
+ return cmp;
+ }
}
return 0;
}
-bool buf_isbol(Buf* buf, size_t off) {
+bool buf_isbol(Buf* buf, size_t off)
+{
size_t bol = buf_bol(buf, off);
return (bol == off);
}
-bool buf_iseol(Buf* buf, size_t off) {
+bool buf_iseol(Buf* buf, size_t off)
+{
Rune r = buf_getrat(buf, off);
return (r == '\r' || r == '\n');
}
-size_t buf_bol(Buf* buf, size_t off) {
- for (; !buf_iseol(buf, off-1); off--);
+size_t buf_bol(Buf* buf, size_t off)
+{
+ for (; !buf_iseol(buf, off-1); off--)
+ {
+ }
return off;
}
-size_t buf_eol(Buf* buf, size_t off) {
- for (; !buf_iseol(buf, off); off++);
+size_t buf_eol(Buf* buf, size_t off)
+{
+ for (; !buf_iseol(buf, off); off++)
+ {
+ }
return off;
}
-void buf_selword(Buf* buf, bool (*isword)(Rune)) {
+void buf_selword(Buf* buf, bool (*isword)(Rune))
+{
Sel sel = selget(buf);
- for (; isword(buf_getrat(buf, sel.beg-1)); sel.beg--);
- for (; isword(buf_getrat(buf, sel.end)); sel.end++);
+ for (; isword(buf_getrat(buf, sel.beg-1)); sel.beg--)
+ {
+ }
+ for (; isword(buf_getrat(buf, sel.end)); sel.end++)
+ {
+ }
buf->selection = sel;
}
-void buf_selall(Buf* buf) {
+void buf_selall(Buf* buf)
+{
buf->selection = (Sel){ .beg = 0, .end = buf_end(buf) };
}
-static bool selquote(Buf* buf, Rune c) {
+static bool selquote(Buf* buf, Rune c)
+{
Rune curr = buf_getc(buf);
size_t nextoff = buf_byrune(buf, buf->selection.end, RIGHT);
Rune prev = buf_getrat(buf, buf_byrune(buf, buf->selection.end, LEFT));
Rune next = buf_getrat(buf, buf_byrune(buf, buf->selection.end, RIGHT));
- if (prev == c || curr == c) {
+ if (prev == c || curr == c)
+ {
size_t bend = buf_end(buf);
buf->selection.beg = buf->selection.end = (prev == c ? buf->selection.end : nextoff);
size_t selend = buf->selection.end;
- for (; selend < bend && buf_getrat(buf, selend) != c; selend = buf_byrune(buf, selend, RIGHT));
+ for (; selend < bend && buf_getrat(buf, selend) != c; selend = buf_byrune(buf, selend, RIGHT))
+ {
+ }
if (buf_getrat(buf, selend) == c)
+ {
buf->selection.end = selend;
+ }
return true;
- } else if (next == c) {
+ }
+ else if (next == c)
+ {
buf->selection.beg = buf->selection.end;
buf->selection.end = nextoff;
size_t selbeg = buf->selection.beg;
- for (; selbeg > 0 && buf_getrat(buf, selbeg) != c; selbeg = buf_byrune(buf, selbeg, LEFT));
+ for (; selbeg > 0 && buf_getrat(buf, selbeg) != c; selbeg = buf_byrune(buf, selbeg, LEFT))
+ {
+ }
if (buf_getrat(buf, selbeg) == c)
+ {
buf->selection.beg = buf_byrune(buf, selbeg, RIGHT);
+ }
return true;
}
return false;
}
-void buf_selctx(Buf* buf, bool (*isword)(Rune)) {
+void buf_selctx(Buf* buf, bool (*isword)(Rune))
+{
size_t bol = buf_bol(buf, buf->selection.end);
Rune curr = buf_getc(buf);
if (curr == '(' || curr == ')')
+ {
selblock(buf, '(', ')');
+ }
else if (curr == '[' || curr == ']')
+ {
selblock(buf, '[', ']');
+ }
else if (curr == '{' || curr == '}')
+ {
selblock(buf, '{', '}');
+ }
else if (curr == '<' || curr == '>')
+ {
selblock(buf, '<', '>');
+ }
else if (buf->selection.end == bol || curr == '\n')
+ {
selline(buf);
+ }
else if (selquote(buf, '"') || selquote(buf, '`') || selquote(buf, '\''))
+ {
; /* condition performs selection */
+ }
else if (risword(curr))
+ {
buf_selword(buf, isword);
+ }
else
+ {
buf_selword(buf, risbigword);
+ }
buf_getcol(buf);
}
-size_t buf_byrune(Buf* buf, size_t pos, int count) {
+size_t buf_byrune(Buf* buf, size_t pos, int count)
+{
int move = (count < 0 ? -1 : 1);
count *= move; // remove the sign if there is one
- for (; count > 0; count--) {
- if (pos > 0 && move < 0) {
+ for (; count > 0; count--)
+ {
+ if (pos > 0 && move < 0)
+ {
if (getb(buf, pos-2) == '\r' && getb(buf, pos-1) == '\n')
+ {
pos -= 2;
+ }
else
+ {
pos += move;
- } else if (pos < buf_end(buf) && move > 0) {
+ }
+ }
+ else if (pos < buf_end(buf) && move > 0)
+ {
if (getb(buf, pos) == '\r' && getb(buf, pos+1) == '\n')
+ {
pos += 2;
+ }
else
+ {
pos += move;
+ }
}
}
return pos;
}
-size_t buf_byword(Buf* buf, size_t off, int count) {
+size_t buf_byword(Buf* buf, size_t off, int count)
+{
int move = (count < 0 ? -1 : 1);
while (nextrune(buf, off, move, risblank))
+ {
off = buf_byrune(buf, off, move);
+ }
- if (nextrune(buf, off, move, risword)) {
+ if (nextrune(buf, off, move, risword))
+ {
while (nextrune(buf, off, move, risword))
+ {
off = buf_byrune(buf, off, move);
+ }
+
if (move > 0)
+ {
off = buf_byrune(buf, off, move);
- } else {
+ }
+ }
+ else
+ {
off = buf_byrune(buf, off, move);
}
return off;
}
-size_t buf_byline(Buf* buf, size_t pos, int count) {
+size_t buf_byline(Buf* buf, size_t pos, int count)
+{
int move = (count < 0 ? -1 : 1);
count *= move; // remove the sign if there is one
- for (; count > 0; count--) {
- if (move < 0) {
+ for (; count > 0; count--)
+ {
+ if (move < 0)
+ {
if (pos > buf_eol(buf, 0))
+ {
pos = buf_byrune(buf, buf_bol(buf, pos), LEFT);
- } else {
+ }
+ }
+ else
+ {
size_t next = buf_byrune(buf, buf_eol(buf, pos), RIGHT);
if (next <= buf_end(buf))
+ {
pos = next;
+ }
}
}
return pos;
}
-bool buf_findstr(Buf* buf, int dir, char* str) {
+bool buf_findstr(Buf* buf, int dir, char* str)
+{
size_t len = strlen(str);
size_t start = buf->selection.beg,
mbeg = (start + dir),
mend = (mbeg + len);
- while (mbeg != start) {
+ while (mbeg != start)
+ {
if ((getb(buf, mbeg) == str[0]) &&
(getb(buf, mend-1) == str[len-1]) &&
(0 == bytes_match(buf, mbeg, mend, str)))
}
mbeg += dir, mend += dir;
if (mend > buf_end(buf))
+ {
mbeg = (dir < 0 ? buf_end(buf)-len : 0), mend = mbeg + len;
+ }
}
return false;
}
-void buf_setln(Buf* buf, size_t line) {
+void buf_setln(Buf* buf, size_t line)
+{
size_t curr = 0, end = buf_end(buf);
- while (line > 1 && curr < end) {
+ while (line > 1 && curr < end)
+ {
size_t next = buf_byline(buf, curr, DOWN);
- if (curr == next) break;
+ if (curr == next)
+ {
+ break;
+ }
line--, curr = next;
}
- buf->selection.beg = buf->selection.end = curr;
+ buf->selection.beg = curr;
+ buf->selection.end = curr;
}
-void buf_getln(Buf* buf, size_t* begln, size_t* endln) {
+void buf_getln(Buf* buf, size_t* begln, size_t* endln)
+{
size_t line = 1, curr = 0, end = buf_end(buf);
size_t sbeg = buf_selbeg(buf), send = buf_selend(buf);
- while (curr < end) {
+ while (curr < end)
+ {
size_t next = buf_byline(buf, curr, DOWN);
- if (curr <= sbeg && sbeg < next) {
+
+ if (curr <= sbeg && sbeg < next)
+ {
*begln = line, *endln = line;
}
- if (curr <= send && send < next) {
+
+ if (curr <= send && send < next)
+ {
*endln = line;
break;
}
- if (curr == next) break;
- line++, curr = next;
+
+ if (curr == next)
+ {
+ break;
+ }
+ line++;
+ curr = next;
}
}
-void buf_getcol(Buf* buf) {
+void buf_getcol(Buf* buf)
+{
Sel sel = buf->selection;
size_t pos = sel.end, curr = buf_bol(buf, pos);
for (sel.col = 0; curr < pos; curr = buf_byrune(buf, curr, 1))
+ {
sel.col += runewidth(sel.col, buf_getrat(buf, curr));
+ }
buf->selection = sel;
}
-void buf_setcol(Buf* buf) {
+void buf_setcol(Buf* buf)
+{
Sel sel = buf->selection;
size_t bol = buf_bol(buf, sel.end);
size_t curr = bol, len = 0, i = 0;
+
/* determine the length of the line in columns */
for (; !buf_iseol(buf, curr); curr++)
+ {
len += runewidth(len, buf_getrat(buf, curr));
+ }
+
/* iterate over the runes until we reach the target column */
- for (sel.end = bol, i = 0; i < sel.col && i < len;) {
+ for (sel.end = bol, i = 0; i < sel.col && i < len;)
+ {
int width = runewidth(i, buf_getrat(buf, sel.end));
sel.end = buf_byrune(buf, sel.end, 1);
if (sel.col >= i && sel.col < (i + width))
+ {
break;
+ }
i += width;
}
buf->selection = sel;
}
-size_t buf_selbeg(Buf* buf) {
+size_t buf_selbeg(Buf* buf)
+{
return selget(buf).beg;
}
-size_t buf_selend(Buf* buf) {
+size_t buf_selend(Buf* buf)
+{
return selget(buf).end;
}
-size_t buf_selsz(Buf* buf) {
+size_t buf_selsz(Buf* buf)
+{
return (selget(buf).end - selget(buf).beg);
}
-void buf_selln(Buf* buf) {
+void buf_selln(Buf* buf)
+{
/* Expand the selection to completely select the lines covered */
Sel sel = selget(buf);
sel.beg = buf_bol(buf, sel.beg);
- if (!buf_iseol(buf, sel.end-1) || sel.end == sel.beg) {
+ if (!buf_iseol(buf, sel.end-1) || sel.end == sel.beg)
+ {
sel.end = buf_eol(buf, sel.end);
sel.end = buf_byrune(buf, sel.end, RIGHT);
}
buf->selection = sel;
}
-void buf_selclr(Buf* buf, int dir) {
+void buf_selclr(Buf* buf, int dir)
+{
require(buf != NULL);
Sel sel = selget(buf);
if (dir > 0)
+ {
sel.beg = sel.end;
+ }
else
+ {
sel.end = sel.beg;
+ }
buf->selection = sel;
}
-bool buf_insel(Buf* buf, size_t off) {
+bool buf_insel(Buf* buf, size_t off)
+{
require(buf != NULL);
return (off >= buf_selbeg(buf) && off < buf_selend(buf));
}
-char* buf_fetch(Buf* buf, bool (*isword)(Rune), size_t off) {
+char* buf_fetch(Buf* buf, bool (*isword)(Rune), size_t off)
+{
require(buf != NULL);
require(isword != NULL);
char* str = NULL;
Sel prev = buf->selection;
- if (!buf_insel(buf, off)) {
+ if (!buf_insel(buf, off))
+ {
buf->selection = (Sel){ .beg = off, .end = off };
buf_selword(buf, isword);
str = buf_gets(buf);
- } else {
+ }
+ else
+ {
str = buf_gets(buf);
}
buf->selection = prev;