]> git.mdlowis.com Git - projs/tide.git/commitdiff
fixed the scrolling logic and line chopping issue for lines with tabs
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 7 Oct 2016 02:36:07 +0000 (22:36 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 7 Oct 2016 02:36:07 +0000 (22:36 -0400)
buf.c
edit.h
screen.c
tests/buf.c

diff --git a/buf.c b/buf.c
index c8c5296db9711e885485460cf66e980924ecfcbe..846ec939b2c55799a7101aa02e98d36317ce3bb7 100644 (file)
--- a/buf.c
+++ b/buf.c
@@ -12,31 +12,29 @@ void buf_load(Buf* buf, char* path) {
     buf->insert_mode = false;
 }
 
-void buf_initsz(Buf* buf, size_t sz) {
-    buf->insert_mode = false;
-    buf->bufsize  = sz;
-    buf->bufstart = (Rune*)malloc(buf->bufsize * sizeof(Rune));
-    buf->bufend   = buf->bufstart + buf->bufsize;
-    buf->gapstart = buf->bufstart;
-    buf->gapend   = buf->bufend;
+void buf_resize(Buf* buf, size_t sz) {
+    /* allocate the new buffer and gap */
+    Buf copy = *buf;
+    copy.bufsize  = sz;
+    copy.bufstart = (Rune*)malloc(copy.bufsize * sizeof(Rune));
+    copy.bufend   = copy.bufstart + copy.bufsize;
+    copy.gapstart = copy.bufstart;
+    copy.gapend   = copy.bufend;
+    /* copy the data from the old buffer to the new one */
+    for (Rune* curr = buf->bufstart; curr < buf->gapstart; curr++)
+        *(copy.gapstart++) = *(curr);
+    for (Rune* curr = buf->gapend; curr < buf->bufend; curr++)
+        *(copy.gapstart++) = *(curr);
+    /* free the buffer and commit the changes */
+    free(buf->bufstart);
+    *buf = copy;
 }
 
 static void syncgap(Buf* buf, unsigned off) {
     assert(off <= buf_end(buf));
     /* If the buffer is full, resize it before syncing */
-    if (0 == (buf->gapend - buf->gapstart)) {
-        Buf newbuf;
-        buf_initsz(&newbuf, buf->bufsize << 1);
-
-        for (Rune* curr = buf->bufstart; curr < buf->gapstart; curr++)
-            *(newbuf.gapstart++) = *(curr);
-        for (Rune* curr = buf->gapend; curr < buf->bufend; curr++)
-            *(newbuf.gapstart++) = *(curr);
-
-        free(buf->bufstart);
-        *buf = newbuf;
-    }
-
+    if (0 == (buf->gapend - buf->gapstart))
+        buf_resize(buf, buf->bufsize << 1);
     /* Move the gap to the desired offset */
     Rune* newpos = (buf->bufstart + off);
     if (newpos < buf->gapstart) {
@@ -49,7 +47,12 @@ static void syncgap(Buf* buf, unsigned off) {
 }
 
 void buf_init(Buf* buf) {
-    buf_initsz(buf, BufSize);
+    buf->insert_mode = false;
+    buf->bufsize  = BufSize;
+    buf->bufstart = (Rune*)malloc(buf->bufsize * sizeof(Rune));
+    buf->bufend   = buf->bufstart + buf->bufsize;
+    buf->gapstart = buf->bufstart;
+    buf->gapend   = buf->bufend;
 }
 
 void buf_clr(Buf* buf) {
@@ -58,13 +61,13 @@ void buf_clr(Buf* buf) {
 }
 
 void buf_del(Buf* buf, unsigned off) {
-    if (!buf->insert_mode) return;
+    if (!buf->insert_mode) { return; }
     syncgap(buf, off);
     buf->gapend++;
 }
 
 void buf_ins(Buf* buf, unsigned off, Rune rune) {
-    if (!buf->insert_mode) return;
+    if (!buf->insert_mode) { return; }
     syncgap(buf, off);
     *(buf->gapstart++) = rune;
 }
@@ -95,9 +98,8 @@ unsigned buf_end(Buf* buf) {
 }
 
 unsigned buf_byrune(Buf* buf, unsigned pos, int count) {
-    (void)buf;
     int move = (count < 0 ? -1 : 1);
-    count *= move;
+    count *= move; // remove the sign if there is one
     for (; count > 0; count--)
         if (move < 0) {
             if (pos > 0) pos--;
@@ -113,7 +115,7 @@ unsigned buf_byline(Buf* buf, unsigned pos, int count) {
     for (; count > 0; count--) {
         if (move < 0) {
             if (pos > buf_eol(buf, 0))
-                pos = buf_bol(buf, pos)-1;
+                pos = buf_bol(buf, buf_bol(buf, pos)-1);
         } else {
             unsigned next = buf_eol(buf, pos)+1;
             if (next < buf_end(buf))
diff --git a/edit.h b/edit.h
index d1596510d836ceaa56b82ecc686fde5959edd258..b442ce2c5d422fea14811739ad03a5300df7a190 100644 (file)
--- a/edit.h
+++ b/edit.h
@@ -130,7 +130,6 @@ typedef struct buf {
 } Buf;
 
 void buf_load(Buf* buf, char* path);
-void buf_initsz(Buf* buf, size_t sz);
 void buf_init(Buf* buf);
 void buf_clr(Buf* buf);
 void buf_del(Buf* buf, unsigned pos);
index 8030085c293aaa39e9a2e171495aae0a3c2f57a0..eb74f5d10e40c221e8b84e90b4092d030d3b01d4 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -117,18 +117,35 @@ static void fill_row(Buf* buf, unsigned row, unsigned pos) {
     }
 }
 
+static unsigned prev_screen_line(Buf* buf, unsigned bol, unsigned off) {
+    unsigned pos = bol;
+    while (true) {
+        //printf("bol: %u, pos: %u, off: %u\n", bol, pos, off);
+        unsigned x = 0;
+        for (; x < NumCols && (pos + x) < off; x++) {
+            Rune r = buf_get(buf, pos+x);
+            x += (r == '\t' ? (TabWidth - (x % TabWidth)) : 1);
+        }
+        if ((pos + x) >= off) break;
+        pos += x;
+    }
+    return pos;
+}
+
 static void scroll_up(Buf* buf, unsigned csr, unsigned first) {
     while (csr < first) {
+        unsigned bol    = buf_bol(buf, first);
+        unsigned prevln = (first == bol ? buf_byline(buf, bol, -1) : bol);
+        prevln = prev_screen_line(buf, prevln, first);
         /* delete the last row and shift the others */
         free(Rows[NumRows - 1]);
         memmove(&Rows[2], &Rows[1], sizeof(Row*) * (NumRows-2));
         Rows[1] = calloc(1, sizeof(Row) + (NumCols * sizeof(Rune)));
-        Rows[1]->off = buf_byline(buf, Rows[2]->off, -1);
+        Rows[1]->off = prevln;
         /* fill in row content */
         fill_row(buf, 1, Rows[1]->off);
         first = Rows[1]->off;
     }
-    screen_reflow(buf);
 }
 
 static void scroll_dn(Buf* buf, unsigned csr, unsigned last) {
index a77c75016d673a18531527c49ad842bdfc592a95..8621735d791c7f2af765d25c17a279342f38245f 100644 (file)
@@ -22,37 +22,6 @@ static bool buf_text_eq(char* str) {
 }
 
 TEST_SUITE(BufferTests) {
-    /* Init and Clear
-     *************************************************************************/
-    TEST(buf_initsz should init the buffer to the given size) {
-        buf_initsz(&TestBuf, 1024);
-        CHECK(TestBuf.bufsize == 1024);
-        CHECK(TestBuf.bufstart == TestBuf.gapstart);
-        CHECK(TestBuf.bufend == TestBuf.gapend);
-        CHECK(TestBuf.bufend - TestBuf.bufstart == 1024);
-        CHECK(TestBuf.gapend - TestBuf.gapstart == 1024);
-        free(TestBuf.bufstart);
-    }
-
-    TEST(buf_init should init the buffer to the default size) {
-        buf_init(&TestBuf);
-        CHECK(TestBuf.bufsize == BufSize);
-        CHECK(TestBuf.bufstart == TestBuf.gapstart);
-        CHECK(TestBuf.bufend == TestBuf.gapend);
-        CHECK(TestBuf.bufend - TestBuf.bufstart == BufSize);
-        CHECK(TestBuf.gapend - TestBuf.gapstart == BufSize);
-    }
-
-    TEST(buf_clr should clear the buffer) {
-        buf_initsz(&TestBuf, 1024);
-        buf_clr(&TestBuf);
-        CHECK(TestBuf.bufsize == BufSize);
-        CHECK(TestBuf.bufstart == TestBuf.gapstart);
-        CHECK(TestBuf.bufend == TestBuf.gapend);
-        CHECK(TestBuf.bufend - TestBuf.bufstart == BufSize);
-        CHECK(TestBuf.gapend - TestBuf.gapstart == BufSize);
-    }
-
     /* Insertions
      *************************************************************************/
     TEST(buf_ins should insert at 0 in empty buf) {
@@ -111,9 +80,9 @@ TEST_SUITE(BufferTests) {
         CHECK(1 == buf_bol(&TestBuf, 1));
     }
 
-    TEST(buf_eol should move to last non newline character of line) {
+    TEST(buf_eol should move to last character of line) {
         set_buffer_text("\nabc\n");
-        CHECK(3 == buf_eol(&TestBuf, 1));
+        CHECK(4 == buf_eol(&TestBuf, 1));
     }
 
     TEST(buf_eol should do nothing for blank line) {