]> git.mdlowis.com Git - projs/tide.git/commitdiff
Implemented scrolling and cursor handling with screen buffer
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 3 Oct 2016 13:24:00 +0000 (09:24 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 3 Oct 2016 13:24:00 +0000 (09:24 -0400)
buf.c
edit.h
screen.c
tests/buf.c
xedit.c

diff --git a/buf.c b/buf.c
index 8981efd22da55fa9ef333392cfa695d05b8f63f9..67ea3916ddeafbebef1de6549b7e79ba14e29042 100644 (file)
--- 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 8c587f43e16c9f548fc8932c0f59b27991f202fb..b38f798f6071599fb75d73b3bb233430143fc3f2 100644 (file)
--- 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
index c7179b1e3e1bdeb07e88d61431d061b593489fd8..33818ada55c02aedcffddf26da468d3af37e8eb8 100644 (file)
--- 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;
index 2977917f6795af8e6515b9e23e16152f512f3f3f..46c5dfafc100b2bf17f46f51228c7c44aa189974 100644 (file)
@@ -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 b482f5a1ad4f565a8f79fe2f367280de908edf5e..08992ba9576fd6377b2131c219b5af6518d0bc17 100644 (file)
--- 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, &gtrclr, 0, 0, X.width, fheight);
-    XftDrawRect(X.xft, &gtrclr, 80 * fwidth, 0, fwidth, X.height);
+    XftDrawRect(X.xft, &gtrclr, 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) {