]> git.mdlowis.com Git - projs/tide.git/commitdiff
Moved the screen scrolling logic from xedit.c to screen.c and fixed some odd behaviors
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 5 Oct 2016 02:26:37 +0000 (22:26 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 5 Oct 2016 02:26:37 +0000 (22:26 -0400)
.gitignore
edit.h
screen.c
xedit.c

index df5a9860fe88c6d479cddf300f95d5bac723da68..1bd9b144d2eb0f0ac14c76e354c4843aaeaee531 100644 (file)
@@ -33,3 +33,5 @@
 *.d
 edit
 unittests
+project.vim
+tags
diff --git a/edit.h b/edit.h
index 9126b525bcaf58eaecf380b22a0a82e8c0bdf647..e4ceccb2b3404906ea0c4c8fe7bd471de196bce5 100644 (file)
--- a/edit.h
+++ b/edit.h
@@ -4,7 +4,6 @@
 #include <stdbool.h>
 #include <string.h>
 
-#include <X11/Xft/Xft.h>
 
 /* Definitons
  *****************************************************************************/
@@ -70,6 +69,7 @@ void screen_clearrow(unsigned row);
 void screen_setrowoff(unsigned row, unsigned off);
 unsigned screen_setcell(unsigned row, unsigned col, Rune r);
 Rune screen_getcell(unsigned row, unsigned col);
+void screen_update(Buf* buf, unsigned crsr, unsigned* csrx, unsigned* csry);
 
 /* Miscellaneous Functions
  *****************************************************************************/
index 27f1fb98e11733abe83f312f4fc2c48ae41f4c2b..2135b9cbe2e13fb513e83adfa0aae65f6f31bc2f 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -4,8 +4,7 @@ static unsigned NumRows = 0;
 static unsigned NumCols = 0;
 static Row** Rows;
 
-void screen_setsize(unsigned nrows, unsigned ncols)
-{
+void screen_setsize(unsigned nrows, unsigned ncols) {
     if (Rows) free(Rows);
     Rows = calloc(nrows, sizeof(Row*));
     for (unsigned i = 0; i < nrows; i++)
@@ -14,24 +13,20 @@ void screen_setsize(unsigned nrows, unsigned ncols)
     NumCols = ncols;
 }
 
-void screen_getsize(unsigned* nrows, unsigned* ncols)
-{
+void screen_getsize(unsigned* nrows, unsigned* ncols) {
     *nrows = NumRows, *ncols = NumCols;
 }
 
-void screen_clear(void)
-{
+void screen_clear(void) {
     for (unsigned i = 0; i < NumRows; i++)
         screen_clearrow(i);
 }
 
-Row* screen_getrow(unsigned row)
-{
+Row* screen_getrow(unsigned row) {
     return (row < NumRows ? Rows[row] : NULL);
 }
 
-void screen_clearrow(unsigned row)
-{
+void screen_clearrow(unsigned row) {
     Row* scrrow = screen_getrow(row);
     if (!scrrow) return;
     for (unsigned i = 0; i < NumCols; i++)
@@ -40,13 +35,11 @@ void screen_clearrow(unsigned row)
     scrrow->len  = 0;
 }
 
-void screen_setrowoff(unsigned row, unsigned off)
-{
+void screen_setrowoff(unsigned row, unsigned off) {
     screen_getrow(row)->off = off;
 }
 
-unsigned screen_setcell(unsigned row, unsigned col, Rune r)
-{
+unsigned screen_setcell(unsigned row, unsigned col, Rune r) {
     if (row >= NumRows || col >= NumCols) return 0;
     Row* scrrow = screen_getrow(row);
     /* write the rune to the screen buf */
@@ -64,9 +57,75 @@ unsigned screen_setcell(unsigned row, unsigned col, Rune r)
     return ncols;
 }
 
-Rune screen_getcell(unsigned row, unsigned col)
-{
+Rune screen_getcell(unsigned row, unsigned col) {
     if (row >= NumRows || col >= NumCols) return 0;
     Row* scrrow = screen_getrow(row);
     return scrrow->cols[col];
 }
+
+static unsigned linelen(Buf* buf, unsigned csr) {
+    unsigned eol = buf_eol(buf, csr);
+    unsigned bol = buf_bol(buf, csr);
+    return (eol - bol);
+}
+
+static void fill_row(Buf* buf, unsigned row, unsigned pos) {
+    for (unsigned x = 0; x < NumCols;) {
+        Rune r = buf_get(buf, pos++);
+        x += screen_setcell(row, x, r);
+        if (r == '\n') break;
+    }
+}
+
+static void scroll_up(Buf* buf, unsigned csr, unsigned first) {
+    while (csr < 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);
+        /* fill in row content */
+        fill_row(buf, 1, Rows[1]->off);
+        first = Rows[1]->off;
+    }
+}
+
+static void scroll_dn(Buf* buf, unsigned csr, unsigned last) {
+    while (csr > last) {
+        /* delete the first row and shift the others */
+        free(Rows[1]);
+        memmove(&Rows[1], &Rows[2], sizeof(Row*) * (NumRows-2));
+        Rows[NumRows-1] = calloc(1, sizeof(Row) + (NumCols * sizeof(Rune)));
+        Rows[NumRows-1]->off = (Rows[NumRows-2]->off + Rows[NumRows-2]->rlen);
+        /* fill in row content */
+        fill_row(buf, NumRows-1, Rows[NumRows-1]->off);
+        last = Rows[NumRows-1]->off + Rows[NumRows-1]->rlen - 1;
+    }
+}
+
+static void sync_view(Buf* buf, unsigned csr) {
+    unsigned first = Rows[1]->off;
+    unsigned last  = Rows[NumRows-1]->off + Rows[NumRows-1]->rlen - 1;
+    if (csr < first) {
+        scroll_up(buf, csr, first);
+    } else if (csr > last) {
+        scroll_dn(buf, csr, last);
+    }
+}
+
+void screen_update(Buf* buf, unsigned csr, unsigned* csrx, unsigned* csry) {
+    sync_view(buf, csr);
+    screen_clearrow(0);
+    unsigned pos = Rows[1]->off;
+    for (unsigned y = 1; y < NumRows; y++) {
+        screen_clearrow(y);
+        screen_setrowoff(y, pos);
+        for (unsigned x = 0; x < NumCols;) {
+            if (csr == pos)
+                *csrx = x, *csry = y;
+            Rune r = buf_get(buf, pos++);
+            x += screen_setcell(y,x,r);
+            if (r == '\n') break;
+        }
+    }
+}
diff --git a/xedit.c b/xedit.c
index c7a4ffad8f54b7570cbf0c95fbe35388e8a77ee7..d243691a5e35db90095b87139eb2f58208e3931f 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -2,6 +2,7 @@
 #include <time.h>
 #include <signal.h>
 #include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
 
 #include "edit.h"
 
@@ -25,9 +26,7 @@ struct {
 } X;
 Buf Buffer;
 bool InsertMode = false;
-unsigned StartRow = 0;
 unsigned CursorPos = 0;
-unsigned EndPos = 0;
 
 void die(char* m) {
     fprintf(stderr, "dying, %s\n", m);
@@ -203,28 +202,6 @@ static void handle_event(XEvent* e) {
     }
 }
 
-static void scroll_up(void) {
-    while (CursorPos < StartRow)
-        StartRow = buf_byline(&Buffer, StartRow, -1);
-}
-
-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; }
-            }
-        }
-        EndPos = pos-1;
-    }
-}
-
 static void redraw(void) {
     int fheight = X.font->height;
     int fwidth  = X.font->max_advance_width;
@@ -234,37 +211,18 @@ static void redraw(void) {
     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 */
-    unsigned nrows, ncols, pos = StartRow;
-    unsigned csrx = 0, csry = 1;
-    screen_getsize(&nrows,&ncols);
-    screen_clearrow(0);
-    for (unsigned y = 1; y < nrows; y++) {
-        screen_clearrow(y);
-        screen_setrowoff(y, pos);
-        for (unsigned x = 0; x < ncols;) {
-            if (CursorPos == pos)
-                csrx = x, csry = y;
-            Rune r = buf_get(&Buffer, pos++);
-            unsigned cols = screen_setcell(y,x,r);
-            x += cols;
-            if (r == '\n') break;
-        }
-    }
-    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, 79 * fwidth, 0, fwidth, X.height);
 
+    /* update the screen buffer and retrieve cursor coordinates */
+    unsigned csrx, csry;
+    screen_update(&Buffer, CursorPos, &csrx, &csry);
+
     /* flush the screen buffer */
+    unsigned nrows, ncols;
+    screen_getsize(&nrows, &ncols);
     for (unsigned y = 0; y < nrows; y++) {
         Row* row = screen_getrow(y);
         XftDrawString32(X.xft, &txtclr, X.font, 0, (y+1) * fheight, (FcChar32*)(row->cols), (row->len));