#include <fcntl.h>
#include <sys/stat.h>
-static void buf_resize(Buf* buf, size_t sz);
-static void log_clear(Log** list);
-static void syncgap(Buf* buf, size_t off);
-static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str);
-static Rune nextrune(Buf* buf, size_t off, int move, bool (*testfn)(Rune));
-static void selline(Buf* buf);
-static void selblock(Buf* buf, Rune first, Rune last);
-static size_t pagealign(size_t sz);
+/* Creation, Resizing, Loading, and Saving
+ ******************************************************************************/
+static size_t pagealign(size_t sz) {
+ size_t pgsize = sysconf(_SC_PAGE_SIZE), alignmask = pgsize - 1;
+ if (sz & alignmask)
+ sz += pgsize - (sz & alignmask);
+ return sz;
+}
void buf_init(Buf* buf) {
/* cleanup old data if there is any */
if (0 == buf_end(buf)) return;
char* wptr;
long fd, nwrite = 0, towrite = 0;
- if (buf->path && (fd = open(buf->path, O_WRONLY|O_CREAT, 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))
}
}
-size_t buf_end(Buf* buf) {
- size_t bufsz = buf->bufend - buf->bufstart;
- size_t gapsz = buf->gapend - buf->gapstart;
- return (bufsz - gapsz);
-}
-
-static void syncgap(Buf* buf, size_t off) {
- assert(off <= buf_end(buf));
- /* If the buffer is full, resize it before syncing */
- if (0 == (buf->gapend - buf->gapstart))
- buf_resize(buf, buf->bufsize << 1);
- /* Move the gap to the desired offset */
- char* newpos = (buf->bufstart + off);
- if (newpos < buf->gapstart)
- while (newpos < buf->gapstart)
- *(--buf->gapend) = *(--buf->gapstart);
- else
- while (newpos > buf->gapstart)
- *(buf->gapstart++) = *(buf->gapend++);
-}
-
static void buf_resize(Buf* buf, size_t sz) {
/* allocate the new buffer and gap */
Buf copy = *buf;
memcpy(buf, ©, sizeof(Buf));
}
-/******************************************************************************/
+static void buf_syncgap(Buf* buf, size_t off) {
+ assert(off <= buf_end(buf));
+ /* If the buffer is full, resize it before syncing */
+ if (0 == (buf->gapend - buf->gapstart))
+ buf_resize(buf, buf->bufsize << 1);
+ /* Move the gap to the desired offset */
+ char* newpos = (buf->bufstart + off);
+ if (newpos < buf->gapstart)
+ while (newpos < buf->gapstart)
+ *(--buf->gapend) = *(--buf->gapstart);
+ else
+ while (newpos > buf->gapstart)
+ *(buf->gapstart++) = *(buf->gapend++);
+}
-static Sel getsel(Buf* buf) {
+static Sel buf_getsel(Buf* buf) {
size_t temp;
Sel sel = buf->selection;
if (sel.end < sel.beg)
return sel;
}
+/* Unod/Redo Operations
+ ******************************************************************************/
+static void log_clear(Log** list) {
+ while (*list) {
+ Log* deadite = *list;
+ *list = (*list)->next;
+ if (deadite->data)
+ free(deadite->data);
+ free(deadite);
+ }
+}
+
+void buf_undo(Buf* buf) {
+}
+
+void buf_redo(Buf* buf) {
+}
+
+void buf_logclear(Buf* buf) {
+ log_clear(&(buf->redo));
+ log_clear(&(buf->undo));
+}
+
+void buf_lastins(Buf* buf) {
+ Sel sel = buf_getsel(buf);
+ // Set selection to last inserted text
+ buf->selection = sel;
+}
+
+/* Basic Operations and Accessors
+ ******************************************************************************/
static void putb(Buf* buf, char b, Sel* p_sel) {
- syncgap(buf, p_sel->end);
+ buf_syncgap(buf, p_sel->end);
*(buf->gapstart++) = b;
p_sel->end = p_sel->end + 1u;
p_sel->beg = p_sel->end;
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;
}
char* buf_gets(Buf* buf) {
- Sel sel = getsel(buf);
+ Sel sel = buf_getsel(buf);
size_t nbytes = sel.end - sel.beg;
char* str = malloc(nbytes+1);
for (size_t i = 0; i < nbytes; i++)
}
void buf_del(Buf* buf) {
- Sel sel = getsel(buf);
+ Sel sel = buf_getsel(buf);
size_t nbytes = sel.end - sel.beg;
if (nbytes > 0) {
buf->status = MODIFIED;
//char* str = buf_gets(buf, &sel);
- syncgap(buf, sel.beg);
+ buf_syncgap(buf, sel.beg);
buf->gapend += nbytes;
sel.end = sel.beg;
buf->selection = sel;
}
}
-/******************************************************************************/
-
-void buf_undo(Buf* buf) {
+/* Positional and Movement Operations
+ ******************************************************************************/
+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;
}
-void buf_redo(Buf* buf) {
+static void selline(Buf* buf) {
+ Sel sel = buf_getsel(buf);
+ sel.beg = buf_bol(buf, sel.end);
+ sel.end = buf_eol(buf, sel.end);
+ sel.end = buf_byrune(buf, sel.end, RIGHT);
+ buf->selection = sel;
}
-void buf_logclear(Buf* buf) {
- log_clear(&(buf->redo));
- log_clear(&(buf->undo));
-}
+static void selblock(Buf* buf, Rune first, Rune last) {
+ Sel sel = buf_getsel(buf);
+ int balance = 0, dir;
+ size_t beg, end = sel.end;
-void buf_lastins(Buf* buf) {
- Sel sel = getsel(buf);
- // Set selection to last inserted text
- buf->selection = sel;
-}
+ /* 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;
-static void log_clear(Log** list) {
- while (*list) {
- Log* deadite = *list;
- *list = (*list)->next;
- if (deadite->data)
- free(deadite->data);
- free(deadite);
+ /* scan for a blanced set of braces */
+ 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;
+
+ /* update the passed in selection */
+ 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; str++, mbeg++) {
+ int cmp = *str - getb(buf, mbeg);
+ if (cmp != 0) return cmp;
+ }
+ return 0;
+}
bool buf_iseol(Buf* buf, size_t off) {
Rune r = buf_getrat(buf, off);
}
void buf_selword(Buf* buf, bool (*isword)(Rune)) {
- Sel sel = getsel(buf);
+ Sel sel = buf_getsel(buf);
for (; isword(buf_getrat(buf, sel.beg-1)); sel.beg--);
for (; isword(buf_getrat(buf, sel.end)); sel.end++);
buf->selection = sel;
return false;
}
-static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str) {
- for (; *str; str++, mbeg++) {
- int cmp = *str - getb(buf, mbeg);
- if (cmp != 0) return cmp;
- }
- return 0;
-}
-
void buf_setln(Buf* buf, size_t line) {
size_t curr = 0, end = buf_end(buf);
while (line > 1 && curr < end) {
buf->selection = sel;
}
-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;
-}
-
-/******************************************************************************/
-
size_t buf_selsz(Buf* buf) {
- Sel sel = getsel(buf);
+ Sel sel = buf_getsel(buf);
return sel.end - sel.beg;
}
}
bool buf_insel(Buf* buf, size_t off) {
- Sel sel = getsel(buf);
+ Sel sel = buf_getsel(buf);
return (off >= sel.beg && off < sel.end);
}
buf->selection = prev;
return str;
}
-
-/******************************************************************************/
-
-static void selline(Buf* buf) {
- Sel sel = getsel(buf);
- sel.beg = buf_bol(buf, sel.end);
- sel.end = buf_eol(buf, sel.end);
- sel.end = buf_byrune(buf, sel.end, RIGHT);
- buf->selection = sel;
-}
-
-static void selblock(Buf* buf, Rune first, Rune last) {
- Sel sel = getsel(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) {
- 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;
-
- /* update the passed in selection */
- if (end > beg) beg++; else end++;
- buf->selection.beg = beg, buf->selection.end = end;
-}
-
-static size_t pagealign(size_t sz) {
- size_t pgsize = sysconf(_SC_PAGE_SIZE), alignmask = pgsize - 1;
- if (sz & alignmask)
- sz += pgsize - (sz & alignmask);
- return sz;
-}
-