static char getb(Buf* buf, size_t off)
{
- if (off >= buf_end(buf))
+ int c = '\n'; // TODO: get rid of this hack
+ if (off < buf_end(buf))
{
- return '\n'; // TODO: get rid of this hack
- }
- size_t bsz = (buf->gapstart - buf->bufstart);
- if (off < bsz)
- {
- return *(buf->bufstart + off);
- }
- else
- {
- return *(buf->gapend + (off - bsz));
+ size_t bsz = (buf->gapstart - buf->bufstart);
+ if (off < bsz)
+ {
+ c = *(buf->bufstart + off);
+ }
+ else
+ {
+ c = *(buf->gapend + (off - bsz));
+ }
}
+ return c;
}
static void putb(Buf* buf, char b, Sel* p_sel)
static void putch(Buf* buf, char b, Sel* p_sel)
{
- if (b == '\r')
- {
- return;
- }
-
- if (b == '\n' && DosLineFeed)
+ if (b != '\r')
{
- putb(buf, '\r', p_sel);
- putb(buf, '\n', p_sel);
- }
- else
- {
- putb(buf, b, p_sel);
+ if (b == '\n' && DosLineFeed)
+ {
+ putb(buf, '\r', p_sel);
+ putb(buf, '\n', p_sel);
+ }
+ else
+ {
+ putb(buf, b, p_sel);
+ }
}
}
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))
- {
- /* allocate the buffer in advance */
- free(buf->bufstart);
- buf->bufsize = pagealign(sb.st_size);
- buf->bufstart = malloc(buf->bufsize);
- buf->bufend = buf->bufstart + buf->bufsize;
- buf->gapstart = buf->bufstart;
- buf->gapend = buf->bufend;
- /* Read the file into the buffer */
- while (sb.st_size && (nread = read(fd, buf->gapstart, sb.st_size)) > 0)
- buf->gapstart += nread, sb.st_size -= nread;
- }
- if (fd > 0)
+ require(buf != NULL);
+ if (path)
{
- close(fd);
- }
+ /* process the file path and address */
+ if (path[0] == '.' && path[1] == '/')
+ {
+ path += 2;
+ }
+ buf->path = strdup(path);
- /* reset buffer state */
- buf->status = NORMAL;
- buf->modtime = (uint64_t)sb.st_mtime;
- buf_logclear(buf);
+ /* 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))
+ {
+ /* allocate the buffer in advance */
+ free(buf->bufstart);
+ buf->bufsize = pagealign(sb.st_size);
+ buf->bufstart = malloc(buf->bufsize);
+ buf->bufend = buf->bufstart + buf->bufsize;
+ buf->gapstart = buf->bufstart;
+ buf->gapend = buf->bufend;
+ /* Read the file into the buffer */
+ 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);
+ }
- /* use the EOL style of the first line to determine EOL style */
- DosLineFeed = (getb(buf, buf_eol(buf, 0)) == '\r');
+ /* reset buffer state */
+ buf->status = NORMAL;
+ buf->modtime = (uint64_t)sb.st_mtime;
+ buf_logclear(buf);
+ /* 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)
{
+ require(buf != NULL);
char* path = buf->path;
buf->path = NULL;
buf_init(buf);
static void trim_whitespace(Buf* buf)
{
- if (!TrimOnSave || !buf_end(buf))
- {
- return;
- }
+ require(buf != NULL);
+ require(buf_end(buf) > 0);
+
Sel sel = buf->selection;
bool swapped = (sel.beg > sel.end);
if (swapped)
int buf_save(Buf* buf, char* path)
{
+ require(buf != NULL);
buf_setpath(buf, path);
- if (0 == buf_end(buf))
+ if (buf_end(buf) > 0)
{
- return buf->status;
- }
-
- trim_whitespace(buf);
+ if (TrimOnSave && (buf_end(buf) > 0))
+ {
+ 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)
- {
- /* write the chunk before the gap */
- wptr = buf->bufstart, towrite = (buf->gapstart - buf->bufstart);
- while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
- wptr += nwrite, towrite -= nwrite;
- /* write the chunk after the gap */
- wptr = buf->gapend, towrite = (buf->bufend - buf->gapend);
- while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
- wptr += nwrite, towrite -= nwrite;
- close(fd);
- /* report success or failure */
- buf->status = (nwrite >= 0 ? NORMAL : ERRORED);
- }
- else
- {
- buf->status = ERRORED;
- }
+ char* wptr;
+ long fd, nwrite = 0, towrite = 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))
+ wptr += nwrite, towrite -= nwrite;
+ /* write the chunk after the gap */
+ wptr = buf->gapend, towrite = (buf->bufend - buf->gapend);
+ while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0))
+ wptr += nwrite, towrite -= nwrite;
+ close(fd);
+ /* report success or failure */
+ buf->status = (nwrite >= 0 ? NORMAL : ERRORED);
+ }
+ else
+ {
+ buf->status = ERRORED;
+ }
- if (buf->status == NORMAL)
- {
- buf->save = buf->undo;
+ if (buf->status == NORMAL)
+ {
+ buf->save = buf->undo;
+ }
}
-
ensure(buf_valid(buf));
return buf->status;
}
static void dumplog(Buf* buf)
{
-#if 0
+#ifdef LOG_DUMPING
printf("\nUndo:\n");
for (Log* log = buf->undo; log; log = log->next)
{
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)
{
- /* reinsert deleted bytes */
- for (char* s = item->data; s && *s; s++, item->end++)
- {
- putb(buf, *s, &(buf->selection));
- }
- free(item->data);
- item->data = NULL;
+ *src = item->next;
buf->selection.beg = item->beg;
buf->selection.end = item->end;
- }
- else
- {
- /* delete the added bytes */
- Sel sel = selget(buf);
- item->data = buf_gets(buf);
- buf_syncgap(buf, sel.beg);
- buf->gapend += (item->end - item->beg);
- sel.end = sel.beg;
- buf->selection = sel;
- item->beg = sel.beg;
- item->end = sel.end;
- }
+ 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
+ {
+ /* delete the added bytes */
+ Sel sel = selget(buf);
+ item->data = buf_gets(buf);
+ buf_syncgap(buf, sel.beg);
+ buf->gapend += (item->end - item->beg);
+ sel.end = sel.beg;
+ buf->selection = sel;
+ 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);
- }
+ /* 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;
+ if (buf->save == buf->undo)
+ {
+ buf->status = NORMAL;
+ }
}
}
void buf_lastins(Buf* buf)
{
Log* log = buf->undo;
- if (!log)
+ if (log)
{
- return;
- }
- Sel sel = {.beg = log->beg, .end = log->end };
- size_t delsize = 0;
- int transid = log->transid;
+ 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)
+ /* try and expand the selected region to encompass related inserts */
+ for (; log && (log->transid == transid); log = log->next)
{
- size_t ibeg = log->beg, iend = log->end - delsize;
- if (iend < ibeg || ibeg > sel.beg || iend < sel.beg)
+ if (!log->data)
{
- break;
+ 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;
+ }
+ sel.beg = ibeg, delsize = 0;
}
- if (ibeg < sel.beg && iend > sel.end)
- {
- break;
- }
- sel.beg = ibeg, delsize = 0;
- }
- else
- {
- /* bail if the delete doesnt overlap */
- if (log->beg != sel.beg)
+ else
{
- break;
+ /* bail if the delete doesnt overlap */
+ if (log->beg != sel.beg)
+ {
+ break;
+ }
+ delsize = strlen(log->data);
}
- delsize = strlen(log->data);
}
+ buf->selection = sel;
}
- buf->selection = sel;
}
/* Basic Operations and Accessors
}
}
- /* bail if we failed to find a block */
- if (balance != 0)
+ /* update the passed in selection if we found a block */
+ if (balance)
{
- return;
- }
-
- /* update the passed in selection */
- if (end > beg)
- {
- beg++;
- }
- else
- {
- end++;
+ if (end > beg)
+ {
+ beg++;
+ }
+ else
+ {
+ end++;
+ }
+ buf->selection.beg = beg;
+ buf->selection.end = end;
}
- buf->selection.beg = beg;
- buf->selection.end = end;
}
static int bytes_match(Buf* buf, size_t mbeg, size_t mend, char* str)
{
+ int ret = 0;
for (; *str && mbeg < mend; str++, mbeg++)
{
int cmp = *str - getb(buf, mbeg);
if (cmp != 0)
{
- return cmp;
+ ret = cmp;
+ break;
}
}
- return 0;
+ return ret;
}
bool buf_isbol(Buf* buf, size_t off)
static bool selquote(Buf* buf, Rune c)
{
+ bool selected = false;
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));
{
buf->selection.end = selend;
}
- return true;
+ selected = true;
}
else if (next == c)
{
{
buf->selection.beg = buf_byrune(buf, selbeg, RIGHT);
}
- return true;
+ selected = true;
}
- return false;
+ return selected;
}
void buf_selctx(Buf* buf, bool (*isword)(Rune))
bool buf_findstr(Buf* buf, int dir, char* str)
{
+ bool found = false;
size_t len = strlen(str);
size_t start = buf->selection.beg,
mbeg = (start + dir),
(0 == bytes_match(buf, mbeg, mend, str)))
{
buf->selection.beg = mbeg, buf->selection.end = mend;
- return true;
+ found = true;
+ break;
}
mbeg += dir, mend += dir;
if (mend > buf_end(buf))
mbeg = (dir < 0 ? buf_end(buf)-len : 0), mend = mbeg + len;
}
}
- return false;
+ return found;
}
void buf_setln(Buf* buf, size_t line)
static bool selection_visible(View* view)
{
- if (!view->rows || !view->nrows)
+ bool visible = true;
+ if (view->rows && view->nrows)
{
- return true;
+ size_t csr = CSRPOS;
+ size_t beg = view->rows[0]->off;
+ size_t end = view->rows[view->nrows-1]->off
+ + view->rows[view->nrows-1]->len;
+ visible = (beg <= csr && csr <= end);
}
- size_t csr = CSRPOS;
- size_t beg = view->rows[0]->off;
- size_t end = view->rows[view->nrows-1]->off
- + view->rows[view->nrows-1]->len;
- return (beg <= csr && csr <= end);
+ return visible;
}
static Sel* getsel(View* view)
static size_t rune_width(View* view, int c, size_t xpos, size_t width)
{
+ size_t sz;
if (c == '\r')
{
- return 0;
+ sz = 0;
}
else if (c == '\n')
{
- return (width-xpos);
+ sz = (width-xpos);
}
else if (c == '\t')
{
- return (glyph_width(view, c) - (xpos % glyph_width(view, c)));
+ sz = (glyph_width(view, c) - (xpos % glyph_width(view, c)));
}
else
{
- return glyph_width(view, c);
+ sz = glyph_width(view, c);
}
+ return sz;
}
size_t view_limitrows(View* view, size_t maxrows)
static size_t getoffset(View* view, size_t row, size_t col)
{
- size_t i = 0, y = 0, idx = view->index + row;
- if (idx >= view->nrows) return 0;
- Row* selrow = view->rows[idx];
- for (; i < selrow->len; i++)
+ size_t ret = 0, i = 0, y = 0, idx = view->index + row;
+ if (idx < view->nrows)
{
- y += selrow->cols[i].width;
- if (col < y)
+ Row* selrow = view->rows[idx];
+ for (; i < selrow->len; i++)
{
- break;
+ y += selrow->cols[i].width;
+ if (col < y)
+ {
+ break;
+ }
}
+ ret = selrow->cols[i].off;
}
- return selrow->cols[i].off;
+ return ret;
}
void view_setcursor(View* view, size_t row, size_t col, bool extsel)
}
size_t glyph_width(View* view, int c) {
+ size_t ret;
FcChar32 rune = (FcChar32)c;
XGlyphInfo extents;
XftFont* font = (&Regions[TAGS] == view ? X.tagfont : X.font);
XftTextExtents32(X.display, font, &rune, 1, &extents);
if (c == '\t')
- return (TabWidth * extents.xOff);
+ {
+ ret = (TabWidth * extents.xOff);
+ }
else
- return extents.xOff;
+ {
+ ret = extents.xOff;
+ }
+ return ret;
}
static void xkeypress(XConf* x, XEvent* e) {
view_insert(win_view(FOCUSED), key);
}
-static void xmousebtn(XConf* x, XEvent* e) {
+static void xmousebtn(XConf* x, XEvent* e)
+{
(void)x;
size_t row, col;
Focused = (e->xbutton.y <= Divider ? TAGS : EDIT);
static Tag* tag_lookup(char* cmd) {
size_t len = 0;
Tag* tags = Builtins;
- for (char* tag = cmd; *tag && !isspace(*tag); tag++, len++);
- while (tags->tag) {
+
+ for (char* tag = cmd; *tag && !isspace(*tag); tag++, len++)
+ {
+ }
+
+ while (tags->tag)
+ {
if (!strncmp(tags->tag, cmd, len))
- return tags;
+ break;
tags++;
}
- return NULL;
+ return (tags->tag ? tags : NULL);
}
static void cmd_exec(char* cmd) {
{ 0, 0, 0, 0 }
};
+#ifndef TEST
static void usage(void) {
printf(
"Usage: %s [FLAGS] [FILE]\n"
exit(1);
}
-#if !defined(TEST)
int main(int argc, char** argv) {
long int line_num = 0;
#define BOOLARG() (EOPTARG(usage()), optarg_[0] == '0' ? 0 : 1)
case 'T': TagString = STRARG(); break;
case 'C': ShellCmd[0] = STRARG(); break;
case 'l': line_num = NUMARG(); break;
+ default: usage(); break;
} OPTEND;
/* setup the shell */
typedef void (*CmdFn)(Cmd* cmd, LineBuf* buf);
-static void lbputc(LineBuf* lbuf, int c) {
- if ((lbuf->length + 2u) >= lbuf->capacity) {
+static void lbputc(LineBuf* lbuf, int c)
+{
+ if ((lbuf->length + 2u) >= lbuf->capacity)
+ {
lbuf->capacity += 2u;
lbuf->buffer = realloc(lbuf->buffer, lbuf->capacity);
}
lbuf->buffer[lbuf->length] = '\0';
}
-static void lbputsn(LineBuf* lbuf, char* s, ssize_t l) {
+static void lbputsn(LineBuf* lbuf, char* s, ssize_t l)
+{
for (ssize_t i = 0; i < l; i++)
lbputc(lbuf, *(s+i));
}
-static void cmd_d(Cmd* cmd, LineBuf* lbuf) {
+static void cmd_d(Cmd* cmd, LineBuf* lbuf)
+{
(void)cmd;
lbuf->flags |= LB_DELETE;
}
-static void cmd_s(Cmd* cmd, LineBuf* lbuf) {
+static void cmd_s(Cmd* cmd, LineBuf* lbuf)
+{
regmatch_t match[10];
LineBuf out = {0};
char* pos = lbuf->buffer;
do {
memset(match, 0, sizeof(match));
- if (!regexec(cmd->regex, pos, 10, match, 0)) {
+ if (!regexec(cmd->regex, pos, 10, match, 0))
+ {
lbputsn(&out, pos, match[0].rm_so);
- for (char* rs = cmd->text; *rs; rs++) {
- if (*rs == '\\') {
+ for (char* rs = cmd->text; *rs; rs++)
+ {
+ if (*rs == '\\')
+ {
rs++;
- if (isdigit(*rs)) {
+ if (isdigit(*rs))
+ {
int i = *rs - '0';
lbputsn(&out, (pos + match[i].rm_so), (match[i].rm_eo - match[i].rm_so));
- } else {
+ }
+ else
+ {
lbputc(&out, *rs);
}
- } else {
+ }
+ else
+ {
lbputc(&out, *rs);
}
}
pos += match[0].rm_eo;
if (!*pos || !(cmd->flags & SUB_GLOBAL))
+ {
lbputsn(&out, pos, (lbuf->length - (pos - lbuf->buffer) - 1));
- } else {
+ }
+ }
+ else
+ {
lbputsn(&out, pos, (lbuf->length - (pos - lbuf->buffer) - 1));
break;
}
['s'] = cmd_s
};
-static int match_addr(Prog* prog, Addr* addr, LineBuf* lbuf) {
+static int match_addr(Prog* prog, Addr* addr, LineBuf* lbuf)
+{
if (addr->type == NONE)
return 1;
else if (addr->type == LINE)
return 0;
}
-static char* rdline(LineBuf* buf, FILE* file) {
+static char* rdline(LineBuf* buf, FILE* file)
+{
buf->length = getline(&(buf->buffer), (size_t*)&(buf->capacity), file);
buf->flags = 0;
if (buf->length <= 0) {
return buf->buffer;
}
-static void parse_fail(char* msg) {
+static void parse_fail(char* msg)
+{
printf("parse error: %s\n", msg);
exit(1);
}
-static char* parse_till(char* script, int term, char** str) {
+static char* parse_till(char* script, int term, char** str)
+{
if (!*script) return script;
char *sbeg = script, *send = script;
for (; *send && *send != term; send++)
return (*send ? send+1 : send);
}
-static char* parse_addr(char* script, Addr* addr) {
- if (isdigit(*script)) {
+static char* parse_addr(char* script, Addr* addr)
+{
+ if (isdigit(*script))
+ {
addr->type = LINE;
for (; *script && isdigit(*script); script++)
addr->u.line = (addr->u.line * 10) + (*script - '0');
- } else if (*script == '/') {
+ }
+ else if (*script == '/')
+ {
addr->type = REGEX;
char* rstr = NULL;
script = parse_till(++script, '/', &rstr);
return script;
}
-static char* parse_sub(char* script, Cmd* cmd) {
+static char* parse_sub(char* script, Cmd* cmd)
+{
int sep = *script++;
if (!sep) return (script-1);
script = parse_till(script, sep, &tstr);
/* parse the flags */
- for (;*script && !isspace(*script); script++) {
- switch (*script) {
+ for (;*script && !isspace(*script); script++)
+ {
+ switch (*script)
+ {
case 'g': cmd->flags |= SUB_GLOBAL; break;
case 'p': cmd->flags |= SUB_PRINT; break;
default: parse_fail("bad substitute flag");
return script;
}
-static Prog* prog_grow(Prog* prog, Cmd** lastcmd) {
+static Prog* prog_grow(Prog* prog, Cmd** lastcmd)
+{
prog = realloc(prog, sizeof(Prog) + ((prog->ncmds + 1) * sizeof(Cmd)));
*lastcmd = &(prog->cmds[prog->ncmds]);
prog->ncmds++;
return prog;
}
-Prog* prog_parse(char* script) {
+Prog* prog_parse(char* script)
+{
Cmd* cmd = NULL;
Prog* prog = calloc(1, sizeof(Prog));
while (*script) {
/* parse the command */
cmd->type = *script;
- switch (*script++) {
+ switch (*script++)
+ {
case 'd':
/* handled above */
break;
return prog;
}
-void prog_free(Prog* prog) {
+void prog_free(Prog* prog)
+{
#define FREE_REGEX(regex) do { regfree(regex); free(regex); } while(0)
for (size_t i = 0; i < prog->ncmds; i++) {
if (prog->cmds[i].addr[0].type == REGEX) FREE_REGEX(prog->cmds[i].addr[0].u.regex);
if (prog->cmds[i].regex) FREE_REGEX(prog->cmds[i].regex);
if (prog->cmds[i].text) free(prog->cmds[i].text);
}
-#undef FREE_REGEX
free(prog);
}
-void prog_exec(Prog* prog, LineBuf* lbuf) {
+void prog_exec(Prog* prog, LineBuf* lbuf)
+{
prog->line++;
- for (size_t i = 0; i < prog->ncmds; i++) {
+ for (size_t i = 0; i < prog->ncmds; i++)
+ {
Cmd* cmd = &(prog->cmds[i]);
- if ((cmd->flags & IN_RANGE) || match_addr(prog, &(cmd->addr[0]), lbuf)) {
- if (cmd->addr[1].type != NONE) {
+ if ((cmd->flags & IN_RANGE) || match_addr(prog, &(cmd->addr[0]), lbuf))
+ {
+ if (cmd->addr[1].type != NONE)
+ {
cmd->flags |= IN_RANGE;
if (match_addr(prog, &(cmd->addr[1]), lbuf))
cmd->flags &= ~IN_RANGE;
}
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
if (argc < 2) return 1;
LineBuf buf = {0};
Prog* prog = prog_parse(argv[1]);
- while (rdline(&buf, stdin)) {
+ while (rdline(&buf, stdin))
+ {
prog_exec(prog, &buf);
if (buf.flags & LB_DELETE) continue;
fwrite(buf.buffer, 1u, buf.length, stdout);
static char* Output = NULL;
static Buf TestBuf = {0};
-static void set_buffer_text(char* str) {
+static void set_buffer_text(char* str)
+{
buf_init(&TestBuf);
buf_puts(&TestBuf, str);
}
-static int buffer_equals(char* str) {
+static int buffer_equals(char* str)
+{
free(Output), Output = NULL;
buf_selall(&TestBuf);
Output = buf_gets(&TestBuf);
return (!strcmp(str, Output));
}
-static int selection_equals(char* str) {
+static int selection_equals(char* str)
+{
free(Output), Output = NULL;
Output = buf_gets(&TestBuf);
return (!strcmp(str, Output));
}
-void setup_buffer(void) {
+void setup_buffer(void)
+{
free(Output), Output = NULL;
buf_init(&TestBuf);
}
-PROPERTY(getc_returns_putc) {
+PROPERTY(getc_returns_putc)
+{
setup_buffer();
buf_putc(&TestBuf, IVAL(0));
TestBuf.selection.end = TestBuf.selection.beg = 0;
return (IVAL(0) == buf_getc(&TestBuf));
}
-PROPERTY(getc_returns_error) {
+PROPERTY(getc_returns_error)
+{
setup_buffer();
buf_putc(&TestBuf, IVAL(0));
TestBuf.selection.end = TestBuf.selection.beg = 0;
return (0xFFFD == buf_getc(&TestBuf));
}
-PROPERTY(gets_returns_puts) {
+PROPERTY(gets_returns_puts)
+{
setup_buffer();
char* input = VAL(0,char*);
buf_puts(&TestBuf, input);
return 1;
}
-PROPERTY(edit_operations_are_reversible) {
+PROPERTY(edit_operations_are_reversible)
+{
setup_buffer();
char* input = VAL(0,char*);
buf_logstart(&TestBuf);
return 1;
}
-void show_codepoint(QCValue* val) {
+void show_codepoint(QCValue* val)
+{
char buf[UTF_MAX+1] = {0};
utf8encode(buf, val->data[0]);
printf("0x%08x (%s)\n", (int)(val->data[0]), buf);
}
-QCValue* GenCodepoint(void) {
+QCValue* GenCodepoint(void)
+{
long cp = 0;
do { cp = qcrandr(32,0x10FFFF); }
while (
return MkLong(cp, show_codepoint);
}
-TEST_SUITE(BufferTests) {
- TEST(buf should adhere to specific properties) {
+TEST_SUITE(BufferTests)
+{
+ TEST(buf should adhere to specific properties)
+ {
QCHECK("getc should return the same printable ascii value inserted with putc",
getc_returns_putc, 1, GenAsciiChar);
QCHECK("gets should return the same printable ascii string inserted with puts",
/* Initializing
*************************************************************************/
- TEST(buf_init should initialize an empty buffer) {
+ TEST(buf_init should initialize an empty buffer)
+ {
buf_init(&TestBuf);
CHECK(TestBuf.status != MODIFIED);
CHECK(TestBuf.bufsize == 8192);
CHECK(TestBuf.redo == NULL);
}
- TEST(buf_init shoud free old buffer and reinitialize) {
+ TEST(buf_init shoud free old buffer and reinitialize)
+ {
buf_init(&TestBuf);
buf_putc(&TestBuf, 'a');
buf_init(&TestBuf);
/* Set Path
*************************************************************************/
- TEST(buf_setpath should do nothing if arg is NULL) {
+ TEST(buf_setpath should do nothing if arg is NULL)
+ {
buf_init(&TestBuf);
TestBuf.path = strdup("foo");
buf_setpath(&TestBuf, NULL);
CHECK(TestBuf.path != NULL);
}
- TEST(buf_setpath should replace the path) {
+ TEST(buf_setpath should replace the path)
+ {
buf_init(&TestBuf);
TestBuf.path = strdup("foo");
buf_setpath(&TestBuf, "bar");
/* Loading
*************************************************************************/
- TEST(buf_load should load a UTF-8 file from disk) {
+ TEST(buf_load should load a UTF-8 file from disk)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/lorem.txt");
CHECK(TestBuf.status != MODIFIED);
CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt"));
}
- TEST(buf_load should load a non UTF-8 file from disk) {
+ TEST(buf_load should load a non UTF-8 file from disk)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/waf");
CHECK(TestBuf.status != MODIFIED);
CHECK(!strcmp(TestBuf.path, "testdocs/waf"));
}
- TEST(buf_load should remove ./ from file path) {
+ TEST(buf_load should remove ./ from file path)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "./testdocs/lorem.txt");
CHECK(TestBuf.status != MODIFIED);
CHECK(!strcmp(TestBuf.path, "testdocs/lorem.txt"));
}
- TEST(buf_reload should reload the file from disk) {
+ TEST(buf_reload should reload the file from disk)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/waf");
free(TestBuf.path);
/* Saving
*************************************************************************/
- TEST(buf_save should save a UTF-8 file to disk) {
+ TEST(buf_save should save a UTF-8 file to disk)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/lorem.txt");
TestBuf.status = MODIFIED;
CHECK(TestBuf.status != MODIFIED);
}
- TEST(buf_save should save a non UTF-8 file to disk) {
+ TEST(buf_save should save a non UTF-8 file to disk)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/waf");
TestBuf.status = MODIFIED;
CHECK(TestBuf.status != MODIFIED);
}
- TEST(buf_save should save a file to disk with unix line endings) {
+ TEST(buf_save should save a file to disk with unix line endings)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/lf.txt");
TestBuf.status = MODIFIED;
CHECK(TestBuf.status != MODIFIED);
}
- TEST(buf_save should save a file to disk with dos line endings) {
+ TEST(buf_save should save a file to disk with dos line endings)
+ {
buf_init(&TestBuf);
buf_load(&TestBuf, "testdocs/crlf.txt");
TestBuf.status = MODIFIED;
/* Movements
*************************************************************************/
// Start of Line
- TEST(buf_bol should return 0 if column 1 of first line) {
+ TEST(buf_bol should return 0 if column 1 of first line)
+ {
set_buffer_text("ab\ncd");
CHECK(0 == buf_bol(&TestBuf, 2));
}
- TEST(buf_bol should return 0 if column 2 of first line) {
+ TEST(buf_bol should return 0 if column 2 of first line)
+ {
set_buffer_text("ab\ncd");
CHECK(0 == buf_bol(&TestBuf, 1));
}
- TEST(buf_bol should return 0 if index points to newline) {
+ TEST(buf_bol should return 0 if index points to newline)
+ {
set_buffer_text("ab\ncd");
CHECK(0 == buf_bol(&TestBuf, 0));
}
- TEST(buf_bol should return 3 if column 1 of second line) {
+ TEST(buf_bol should return 3 if column 1 of second line)
+ {
set_buffer_text("ab\ncd");
CHECK(3 == buf_bol(&TestBuf, 3));
}
/* Cursor Column Tracking
*************************************************************************/
- TEST(buf_getcol should return the column associated with the position) {
+ TEST(buf_getcol should return the column associated with the position)
+ {
set_buffer_text("abcdef");
TestBuf.selection = (Sel){ .end = 4 };
buf_getcol(&TestBuf);
CHECK(4 == TestBuf.selection.col);
}
- TEST(buf_getcol should return the column associated with the position on second line) {
+ TEST(buf_getcol should return the column associated with the position on second line)
+ {
set_buffer_text("abcdef\nabcdef");
TestBuf.selection = (Sel){ .end = 7 };
buf_getcol(&TestBuf);
CHECK(0 == TestBuf.selection.col);
}
- TEST(buf_getcol should handle tab characters) {
+ TEST(buf_getcol should handle tab characters)
+ {
set_buffer_text("\tabcdef");
TestBuf.selection = (Sel){ .end = 1 };
buf_getcol(&TestBuf);
CHECK(4 == TestBuf.selection.col);
}
- TEST(buf_setcol should set the column to column 1 of second line) {
+ TEST(buf_setcol should set the column to column 1 of second line)
+ {
set_buffer_text("abc\ndef");
TestBuf.selection = (Sel){ .end = 4, .col = 0 };
buf_setcol(&TestBuf);