From 7e4f2f685f2c5bb222085ad8910722e0d72529b3 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 3 Oct 2016 09:24:00 -0400 Subject: [PATCH] Implemented scrolling and cursor handling with screen buffer --- buf.c | 44 +++++++++------------------ edit.h | 2 +- screen.c | 1 - tests/buf.c | 66 ++++++++++++++++++++-------------------- xedit.c | 88 +++++++++++++++++++++++++++-------------------------- 5 files changed, 94 insertions(+), 107 deletions(-) diff --git a/buf.c b/buf.c index 8981efd..67ea391 100644 --- a/buf.c +++ b/buf.c @@ -105,37 +105,17 @@ unsigned buf_end(Buf* buf) return (bufsz - gapsz); } -static unsigned move_back(Buf* buf, unsigned pos) { - if (pos == 0) return 0; - if (buf_get(buf, pos) == '\n' && - buf_get(buf, pos-1) == '\n' && - buf_get(buf, pos-2) != '\n') - pos = pos - 2; - else if (buf_get(buf, pos) != '\n' && - buf_get(buf, pos-1) == '\n' && - buf_get(buf, pos-2) != '\n') - pos = pos - 2; - else - pos = pos - 1; - return pos; -} - -static unsigned move_forward(Buf* buf, unsigned pos) { - if (pos+2 >= buf_end(buf)) return buf_end(buf)-2; - if (buf_get(buf, pos) != '\n' && - buf_get(buf, pos+1) == '\n') - pos = pos + 2; - else - pos = pos + 1; - return pos; -} - unsigned buf_byrune(Buf* buf, unsigned pos, int count) { + (void)buf; int move = (count < 0 ? -1 : 1); count *= move; for (; count > 0; count--) - pos = (move > 0 ? &move_forward : &move_back)(buf, pos); + if (move < 0) { + if (pos > 0) pos--; + } else { + if (pos < buf_end(buf)-1) pos++; + } return pos; } @@ -169,8 +149,14 @@ unsigned buf_byline(Buf* buf, unsigned pos, int count) int move = (count < 0 ? -1 : 1); count *= move; // remove the sign if there is one unsigned col = get_column(buf, pos); - for (; count > 0; count--) - pos = (move < 0 ? move_back(buf, buf_bol(buf, pos)) - : move_forward(buf, buf_eol(buf, pos))); + for (; count > 0; count--) { + if (move < 0) { + if (pos > buf_eol(buf, 0)) + pos = buf_bol(buf, pos)-2; + } else { + if (pos < buf_end(buf)-2) + pos = buf_eol(buf, pos)+2; + } + } return set_column(buf, pos, col); } diff --git a/edit.h b/edit.h index 8c587f4..b38f798 100644 --- a/edit.h +++ b/edit.h @@ -104,7 +104,7 @@ static const Color Palette[][2] = { }; #ifdef __MACH__ -#define FONTNAME "Monaco:pixelsize=15:antialias=true:autohint=true" +#define FONTNAME "Inconsolata:pixelsize=14:antialias=true:autohint=true" #else #define FONTNAME "Liberation Mono:pixelsize=14:antialias=true:autohint=true" #endif diff --git a/screen.c b/screen.c index c7179b1..33818ad 100644 --- a/screen.c +++ b/screen.c @@ -1,6 +1,5 @@ #include "edit.h" -static unsigned FileOffset = 0; static unsigned NumRows = 0; static unsigned NumCols = 0; static Row** Rows; diff --git a/tests/buf.c b/tests/buf.c index 2977917..46c5dfa 100644 --- a/tests/buf.c +++ b/tests/buf.c @@ -139,44 +139,44 @@ TEST_SUITE(BufferTests) { TEST(buf_byrune should do nothing for +1 at end of file) { set_buffer_text("abc\n"); - CHECK(2 == buf_byrune(&TestBuf, 2, 1)); + CHECK(3 == buf_byrune(&TestBuf, 3, 1)); } TEST(buf_byrune should do nothing for +2 at end of file) { set_buffer_text("abc\n"); - CHECK(2 == buf_byrune(&TestBuf, 2, 2)); - } - - TEST(buf_byrune should skip newlines for -1) - { - set_buffer_text("ab\ncd\n"); - CHECK(1 == buf_byrune(&TestBuf, 3, -1)); - } - - TEST(buf_byrune should skip newlines for +1) - { - set_buffer_text("ab\ncd\n"); - CHECK(3 == buf_byrune(&TestBuf, 1, 1)); - } - - TEST(buf_byrune should not skip blank lines for -1) - { - set_buffer_text("ab\n\ncd\n"); - CHECK(3 == buf_byrune(&TestBuf, 4, -1)); - } - - TEST(buf_byrune should not skip blank lines for +1) - { - set_buffer_text("ab\n\ncd\n"); - CHECK(3 == buf_byrune(&TestBuf, 1, 1)); - } - - TEST(buf_byrune should move from blank line to non-blank line for -1) - { - set_buffer_text("ab\n\ncd\n"); - CHECK(1 == buf_byrune(&TestBuf, 3, -1)); - } + CHECK(3 == buf_byrune(&TestBuf, 3, 2)); + } + + //TEST(buf_byrune should skip newlines for -1) + //{ + // set_buffer_text("ab\ncd\n"); + // CHECK(1 == buf_byrune(&TestBuf, 3, -1)); + //} + + //TEST(buf_byrune should skip newlines for +1) + //{ + // set_buffer_text("ab\ncd\n"); + // CHECK(3 == buf_byrune(&TestBuf, 1, 1)); + //} + + //TEST(buf_byrune should not skip blank lines for -1) + //{ + // set_buffer_text("ab\n\ncd\n"); + // CHECK(3 == buf_byrune(&TestBuf, 4, -1)); + //} + + //TEST(buf_byrune should not skip blank lines for +1) + //{ + // set_buffer_text("ab\n\ncd\n"); + // CHECK(3 == buf_byrune(&TestBuf, 1, 1)); + //} + + //TEST(buf_byrune should move from blank line to non-blank line for -1) + //{ + // set_buffer_text("ab\n\ncd\n"); + // CHECK(1 == buf_byrune(&TestBuf, 3, -1)); + //} TEST(buf_byrune should move from blank line to non-blank line for +1) { diff --git a/xedit.c b/xedit.c index b482f5a..08992ba 100644 --- a/xedit.c +++ b/xedit.c @@ -27,18 +27,13 @@ Buf Buffer; bool InsertMode = false; unsigned StartRow = 0; unsigned CursorPos = 0; +unsigned EndPos = 0; void die(char* m) { fprintf(stderr, "dying, %s\n", m); exit(1); } -static uint64_t time_ms(void) { - struct timespec ts; - timespec_get(&ts, TIME_UTC); - return (ts.tv_sec * 1000000000L + ts.tv_nsec) / 1000000L; -} - static XftColor xftcolor(enum ColorId cid) { Color c = Palette[cid][ColorBase]; XftColor xc; @@ -137,11 +132,11 @@ static void handle_key(XEvent* e) { break; case XK_Down: - StartRow = buf_byline(&Buffer, StartRow, 1); + CursorPos = buf_byline(&Buffer, CursorPos, 1); break; case XK_Up: - StartRow = buf_byline(&Buffer, StartRow, -1); + CursorPos = buf_byline(&Buffer, CursorPos, -1); break; } } @@ -155,65 +150,72 @@ static void handle_mousebtn(XEvent* e) { case Button3: /* Right Button */ break; case Button4: /* Wheel Up */ - StartRow = buf_byline(&Buffer, StartRow, -4); break; case Button5: /* Wheel Down */ - StartRow = buf_byline(&Buffer, StartRow, 4); break; } } static void handle_event(XEvent* e) { switch (e->type) { - case FocusIn: - if (X.xic) XSetICFocus(X.xic); - break; - - case FocusOut: - if (X.xic) XUnsetICFocus(X.xic); - break; - - case Expose: // Draw the window - XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); - XFlush(X.display); - break; - + case FocusIn: if (X.xic) XSetICFocus(X.xic); break; + case FocusOut: if (X.xic) XUnsetICFocus(X.xic); break; + case ButtonPress: handle_mousebtn(e); break; + case KeyPress: handle_key(e); break; case ConfigureNotify: // Resize the window if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) { X.width = e->xconfigure.width; X.height = e->xconfigure.height; X.pixmap = XCreatePixmap(X.display, X.window, X.width, X.height, X.depth); X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap); - screen_setsize(X.width / X.font->max_advance_width, X.height / X.font->height); + screen_setsize(X.height / X.font->height, X.width / X.font->max_advance_width); } break; + } +} - case ButtonPress: // Mouse button handling - handle_mousebtn(e); - break; +static void scroll_up(void) { + while (CursorPos < StartRow) + StartRow = buf_byline(&Buffer, StartRow, -1); +} - case KeyPress: // Keyboard events - handle_key(e); - break; +static void scroll_dn(void) { + unsigned nrows, ncols; + screen_getsize(&nrows, &ncols); + while (CursorPos > EndPos) { + StartRow = buf_byline(&Buffer, StartRow, 1); + unsigned pos = StartRow; + for (unsigned y = 1; y < nrows; y++) { + for (unsigned x = 0; x < ncols; x++) { + Rune r = buf_get(&Buffer, pos++); + if (r == '\n') { break; } + if (r == '\t') { x += 4; break; } + } + } + EndPos = pos-1; } } static void redraw(void) { - uint64_t tstart; int fheight = X.font->height; int fwidth = X.font->max_advance_width; - /* Allocate the colors */ XftColor bkgclr = xftcolor(CLR_BASE03); XftColor gtrclr = xftcolor(CLR_BASE02); XftColor csrclr = xftcolor(CLR_BASE3); XftColor txtclr = xftcolor(CLR_BASE0); + /* Scroll up or down if needed */ + if (CursorPos < StartRow) + scroll_up(); + else if (CursorPos > EndPos) + scroll_dn(); + /* Update the screen buffer */ - tstart = time_ms(); unsigned nrows, ncols, pos = StartRow; - unsigned csrx = 0, csry = 0; + unsigned csrx = 0, csry = 1; screen_getsize(&nrows,&ncols); + screen_clearrow(0); for (unsigned y = 1; y < nrows; y++) { screen_clearrow(y); for (unsigned x = 0; x < ncols; x++) { @@ -225,32 +227,32 @@ static void redraw(void) { screen_setcell(y,x,r); } } - printf("\nT1: %lu\n", time_ms() - tstart); + EndPos = pos-1; /* draw the background colors */ XftDrawRect(X.xft, &bkgclr, 0, 0, X.width, X.height); XftDrawRect(X.xft, >rclr, 0, 0, X.width, fheight); - XftDrawRect(X.xft, >rclr, 80 * fwidth, 0, fwidth, X.height); + XftDrawRect(X.xft, >rclr, 79 * fwidth, 0, fwidth, X.height); /* flush the screen buffer */ - tstart = time_ms(); for (unsigned y = 0; y < nrows; y++) { Row* row = screen_getrow(y); if (row->len > 0) - XftDrawString32(X.xft, &txtclr, X.font, 0, (y+2) * fheight, (FcChar32*)(row->cols), (row->len)); + XftDrawString32(X.xft, &txtclr, X.font, 0, (y+1) * fheight, (FcChar32*)(row->cols), (row->len)); } - printf("T2: %lu\n", time_ms() - tstart); /* Place cursor on screen */ Rune csrrune = screen_getcell(csry,csrx); - XftDrawRect(X.xft, &txtclr, csrx * fwidth, (csry+1) * fheight + 3, fwidth, fheight); - XftDrawString32(X.xft, &bkgclr, X.font, csrx * fwidth, (csry+2) * fheight, (FcChar32*)&(csrrune), 1); + if (InsertMode) { + XftDrawRect(X.xft, &csrclr, csrx * fwidth, csry * fheight + X.font->descent, 2, fheight); + } else { + XftDrawRect(X.xft, &csrclr, csrx * fwidth, csry * fheight + X.font->descent, fwidth, fheight); + XftDrawString32(X.xft, &bkgclr, X.font, csrx * fwidth, (csry+1) * fheight, (FcChar32*)&csrrune, 1); + } /* flush pixels to the screen */ - tstart = time_ms(); XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); XFlush(X.display); - printf("T3: %lu\n", time_ms() - tstart); } int main(int argc, char** argv) { -- 2.54.0