#include <stdc.h>
+#include <dbc.h>
#include <utf.h>
#include <edit.h>
#include <ctype.h>
#include <sys/stat.h>
#include "config.h"
+static bool buf_logvalid(Log* log) {
+ bool result = true;
+ for (; result && log; log = log->next) {
+ if (log->data) {
+ result = result && (log->beg == log->end);
+ } else {
+ result = result && (log->end > log->beg);
+ }
+ }
+ return result;
+}
+
+static bool buf_selvalid(Buf* buf) {
+ (void)buf;
+ return true;
+}
+
+static bool buf_valid(Buf* buf) {
+ return (
+ (buf->bufsize > 0)
+ && (buf->bufstart != NULL)
+ && (buf->bufend != NULL)
+ && (buf->gapstart != NULL)
+ && (buf->gapend != NULL)
+ && (buf->bufstart < buf->bufend)
+ && (buf->gapstart <= buf->gapend)
+ && (buf->gapstart >= buf->bufstart)
+ && (buf->gapend >= buf->bufstart)
+ && (buf->gapstart <= buf->bufend)
+ && (buf->gapend <= buf->bufend)
+ && (buf_logvalid(buf->undo))
+ && (buf_logvalid(buf->redo))
+ && (buf_selvalid(buf))
+ );
+}
+
/* Creation, Resizing, Loading, and Saving
******************************************************************************/
static size_t pagealign(size_t sz) {
buf->redo = NULL;
buf->transid = -1;
buf->selection = (Sel){0,0,0};
- assert(buf->bufstart);
+ ensure(buf_valid(buf));
}
void buf_setpath(Buf* buf, char* path) {
if (path) {
free(buf->path);
buf->path = strdup(path);
+ ensure(buf->path != NULL);
}
}
/* use the EOL style of the first line to determine EOL style */
DosLineFeed = (getb(buf, buf_eol(buf, 0)) == '\r');
+
+ ensure(buf_valid(buf));
}
void buf_reload(Buf* buf) {
}
if (buf->status == NORMAL)
buf->save = buf->undo;
+
+ ensure(buf_valid(buf));
return buf->status;
}
void buf_undo(Buf* buf) {
log_swap(buf, &(buf->undo), &(buf->redo));
+ ensure(buf_valid(buf));
}
void buf_redo(Buf* buf) {
log_swap(buf, &(buf->redo), &(buf->undo));
+ ensure(buf_valid(buf));
}
void buf_logclear(Buf* buf) {
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) {
while (*s) putch(buf, *(s++), &(buf->selection));
log_add(buf, beg, buf_getsel(buf).end, NULL);
}
+ ensure(buf_valid(buf));
}
int buf_getc(Buf* buf) {
buf->selection = sel;
log_add(buf, sel.beg, sel.end, str);
}
+ ensure(buf_valid(buf));
}
/* Positional and Movement Operations
}
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)) {
#include <stdc.h>
+#include <dbc.h>
#include <utf.h>
#include <edit.h>
#include <ctype.h>
#include "config.h"
+static bool view_valid(View* view) {
+ return (
+ (view->sync_flags <= 3u)
+ && (!view->nrows || view->index < view->nrows)
+// && (view->width > 0)
+// && (view->nvisible > 0)
+// && (view->nrows > 0)
+// && (view->rows != NULL)
+ );
+}
+
/* Provided by x11.c */
extern size_t glyph_width(View* view, int c);
}
void view_init(View* view, char* file) {
+ require(view != NULL);
clear_rows(view, 0);
view->sync_flags |= (CURSOR|CENTER);
view->index = 0;
/* load the file and jump to the address returned from the load function */
buf_init(BUF);
if (file) buf_load(BUF, file);
+ ensure(view_valid(view));
}
void view_reload(View* view) {
+ require(view != NULL);
if (view->buffer.path) {
buf_reload(BUF);
view->sync_flags |= (CURSOR|CENTER);
}
+ ensure(view_valid(view));
}
void view_sync(View* view) {
+ require(view != NULL);
view->sync_flags |= (CURSOR|CENTER);
+ ensure(view_valid(view));
}
static size_t rune_width(View* view, int c, size_t xpos, size_t width) {
}
size_t view_limitrows(View* view, size_t maxrows) {
+ require(view != NULL);
size_t nrows = 1, off = 0, xpos = 0;
while (nrows < maxrows && off < buf_end(&(view->buffer))) {
Rune rune = buf_getrat(&(view->buffer), off);
off = buf_byrune(&(view->buffer), off, RIGHT);
}
}
+ ensure(nrows >= 1);
return nrows;
}
}
void view_resize(View* view, size_t width, size_t nrows) {
+ require(view != NULL);
+ require(width > 0);
+ require(nrows > 0);
if (view->width == width && view->nvisible == nrows)
return;
size_t off = (view->nrows && view->index < view->nrows ? view->rows[view->index]->off : 0);
resize(view, width, nrows, off);
+ ensure(view_valid(view));
}
void view_update(View* view) {
+ require(view != NULL);
/* refill the view contents to make sure updates are visible */
size_t off = view->rows[view->index]->off;
clear_rows(view, view->index);
}
view->sync_flags = 0;
}
+ ensure(view_valid(view));
}
Row* view_getrow(View* view, size_t row) {
}
void view_byrune(View* view, int move, bool extsel) {
+ require(view != NULL);
move_selection(view, extsel, move, buf_byrune);
+ ensure(view_valid(view));
}
void view_byword(View* view, int move, bool extsel) {
+ require(view != NULL);
move_selection(view, extsel, move, buf_byword);
+ ensure(view_valid(view));
}
void view_byline(View* view, int move, bool extsel) {
+ require(view != NULL);
move_selection(view, extsel, move, buf_byline);
+ ensure(view_valid(view));
}
static size_t getoffset(View* view, size_t row, size_t col) {
if (!extsel)
getsel(view)->beg = getsel(view)->end;
buf_getcol(BUF);
+ ensure(view_valid(view));
}
void view_selword(View* view, size_t row, size_t col) {
if (row != SIZE_MAX && col != SIZE_MAX)
view_setcursor(view, row, col, false);
buf_selword(BUF, risbigword);
+ ensure(view_valid(view));
}
void view_selprev(View* view) {
buf_lastins(BUF);
else
buf_selclr(BUF, RIGHT);
+ ensure(view_valid(view));
}
void view_select(View* view, size_t row, size_t col) {
view_setcursor(view, row, col, false);
buf_selctx(BUF, risword);
+ ensure(view_valid(view));
}
size_t view_selsize(View* view) {
size_t off = getoffset(view, row, col);
if (off != SIZE_MAX)
str = buf_fetch(BUF, isword, off);
+ ensure(view_valid(view));
return str;
}
bool view_findstr(View* view, int dir, char* str) {
bool found = buf_findstr(BUF, dir, str);
view->sync_flags |= (CURSOR|CENTER);
+ ensure(view_valid(view));
return found;
}
buf_putc(BUF, rune);
}
move_to(view, false, CSRPOS);
+ ensure(view_valid(view));
}
void view_delete(View* view, int dir, bool byword) {
(byword ? view_byword : view_byrune)(view, dir, true);
buf_del(BUF);
move_to(view, false, CSRPOS);
+ ensure(view_valid(view));
}
void view_jumpto(View* view, bool extsel, size_t off) {
move_to(view, extsel, off);
+ ensure(view_valid(view));
}
void view_bol(View* view, bool extsel) {
unsigned pos = CSRPOS;
pos = (pos == bol || pos > boi ? boi : bol);
move_to(view, extsel, pos);
+ ensure(view_valid(view));
}
void view_eol(View* view, bool extsel) {
move_to(view, extsel, buf_eol(BUF, CSRPOS));
getsel(view)->col = -1; // Peg cursor to line end
+ ensure(view_valid(view));
}
void view_bof(View* view, bool extsel) {
view_jumpto(view, extsel, 0);
+ ensure(view_valid(view));
}
void view_eof(View* view, bool extsel) {
view_jumpto(view, extsel, buf_end(BUF));
+ ensure(view_valid(view));
}
void view_setln(View* view, size_t line) {
buf_setln(BUF, line);
buf_selln(BUF);
}
+ ensure(view_valid(view));
}
void view_undo(View* view) {
buf_undo(BUF);
view->sync_flags |= CURSOR;
if (!selection_visible(view)) view->sync_flags |= CENTER;
+ ensure(view_valid(view));
}
void view_redo(View* view) {
buf_redo(BUF);
view->sync_flags |= CURSOR;
if (!selection_visible(view)) view->sync_flags |= CENTER;
+ ensure(view_valid(view));
}
void view_paste(View* view, char* str) {
view_putstr(view, str);
buf_logstop(BUF);
view_selprev(view);
+ ensure(view_valid(view));
}
void view_putstr(View* view, char* str) {
buf_puts(BUF, str);
+ ensure(view_valid(view));
}
char* view_getstr(View* view) {
char* view_getcmd(View* view) {
if (!view_selsize(view))
buf_selctx(BUF, riscmd);
+ ensure(view_valid(view));
return view_getstr(view);
}
void view_selctx(View* view) {
if (!view_selsize(view))
buf_selctx(BUF, risword);
+ ensure(view_valid(view));
}
char* view_getctx(View* view) {
view_selctx(view);
+ ensure(view_valid(view));
return view_getstr(view);
}
else
scroll_dn(view);
}
+ ensure(view_valid(view));
}
void view_scrollpage(View* view, int move) {
move = (move < 0 ? -1 : 1) * view->nrows;
view_scroll(view, move);
+ ensure(view_valid(view));
}
Rune view_getrune(View* view) {
size_t last = lastrow->cols[lastrow->len-1].off;
if (csr < first || csr > last)
resize(view, view->width, view->nrows, csr);
+ ensure(view_valid(view));
}
void view_selectall(View* view) {
buf_selall(BUF);
view->sync_flags |= CURSOR;
+ ensure(view_valid(view));
}
void view_selectobj(View* view, bool (*istype)(Rune)) {
buf_selword(BUF, istype);
view->sync_flags |= CURSOR;
+ ensure(view_valid(view));
}