]> git.mdlowis.com Git - projs/tide.git/commitdiff
implemented color logic for screen buffer and adjusted colors for the status bar
authorMichael D. Lowis <mike@mdlowis.com>
Fri, 21 Oct 2016 02:07:00 +0000 (22:07 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Fri, 21 Oct 2016 02:07:00 +0000 (22:07 -0400)
edit.h
mouse.c
screen.c
tests/tests.c
xedit.c

diff --git a/edit.h b/edit.h
index b6d013cb6206bc62cb71f9a6245d4b3e903e831e..3d136a78491f549127bb9578566195ecb75ede39 100644 (file)
--- a/edit.h
+++ b/edit.h
@@ -184,9 +184,8 @@ void handle_mouse(MouseEvent* mevnt);
 /* Screen management functions
  *****************************************************************************/
 typedef struct {
-    Rune rune;
-    uint8_t fg;
-    uint8_t bg;
+    uint32_t attr; /* attributes  applied to this cell */
+    Rune rune;     /* rune value for the cell */
 } UGlyph;
 
 typedef struct {
@@ -202,7 +201,7 @@ void screen_setsize(Buf* buf, unsigned nrows, unsigned ncols);
 void screen_getsize(unsigned* nrows, unsigned* ncols);
 Row* screen_getrow(unsigned row);
 void screen_clearrow(unsigned row);
-unsigned screen_setcell(unsigned row, unsigned col, Rune r);
+unsigned screen_setcell(unsigned row, unsigned col, uint32_t attr, Rune r);
 UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth);
 
 /* Color Scheme Handling
diff --git a/mouse.c b/mouse.c
index ae3073ce0c0b19fff203e8ff2cf6dbc389c2726b..f6c602d2e9824ae88576332ea43b8ccf3ecf437b 100644 (file)
--- a/mouse.c
+++ b/mouse.c
@@ -5,7 +5,8 @@ void unused(MouseEvent* mevnt) {
 }
 
 void move_cursor(MouseEvent* mevnt) {
-    CursorPos = screen_getoff(&Buffer, CursorPos, mevnt->y, mevnt->x);
+    if (mevnt->y == 0) return;
+    CursorPos = screen_getoff(&Buffer, CursorPos, mevnt->y-1, mevnt->x);
     TargetCol = buf_getcol(&Buffer, CursorPos);
 }
 
index 7fbe46dd069f02c49dfe54d597d14a7d9bc9d039..cb084cbe9df2ae0e0071c3233b5cc978fb90fc7e 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -4,17 +4,25 @@ static unsigned NumRows = 0;
 static unsigned NumCols = 0;
 static Row** Rows;
 
+#define ATTR_NORMAL   (CLR_BASE03 << 8 | CLR_BASE0)
+#define ATTR_SELECTED (CLR_BASE0  << 8 | CLR_BASE03)
+
+static unsigned fill_row(Buf* buf, unsigned row, unsigned pos) {
+    screen_getrow(row)->off = pos;
+    screen_clearrow(row);
+    for (unsigned x = 0; x < NumCols;) {
+        uint32_t attr = (DotBeg <= pos && pos < DotEnd ? ATTR_SELECTED : ATTR_NORMAL);
+        Rune r = buf_get(buf, pos++);
+        x += screen_setcell(row, x, attr, r);
+        if (buf_iseol(buf, pos-1)) break;
+    }
+    return pos;
+}
+
 static void screen_reflow(Buf* buf) {
     unsigned pos = Rows[0]->off;
-    for (unsigned y = 0; y < NumRows; y++) {
-        screen_clearrow(y);
-        screen_getrow(y)->off = pos;
-        for (unsigned x = 0; x < NumCols;) {
-            Rune r = buf_get(buf, pos++);
-            x += screen_setcell(y,x,r);
-            if (buf_iseol(buf, pos-1)) break;
-        }
-    }
+    for (unsigned y = 0; y < NumRows; y++)
+        pos = fill_row(buf, y, pos);
 }
 
 void screen_setsize(Buf* buf, unsigned nrows, unsigned ncols) {
@@ -72,19 +80,22 @@ void screen_clearrow(unsigned row) {
     scrrow->len  = 0;
 }
 
-unsigned screen_setcell(unsigned row, unsigned col, Rune r) {
+unsigned screen_setcell(unsigned row, unsigned col, uint32_t attr, Rune r) {
     if (row >= NumRows || col >= NumCols) return 0;
     Row* scrrow = screen_getrow(row);
     int ncols = runewidth(col, r);
     /* write the rune to the screen buf */
+    scrrow->cols[col].attr = attr;
     if (r == '\t' || r == '\n' || r == RUNE_CRLF)
         scrrow->cols[col].rune = ' ';
     else
         scrrow->cols[col].rune = r;
     /* Update lengths */
     scrrow->rlen += 1;
-    for (int i = 1; i < ncols; i++)
+    for (int i = 1; i < ncols; i++) {
+        scrrow->cols[col].attr = attr;
         scrrow->cols[col+i].rune = '\0';
+    }
     if ((col + ncols) > scrrow->len)
         scrrow->len = col + ncols;
     return ncols;
@@ -100,15 +111,6 @@ UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth) {
     return glyph;
 }
 
-static void fill_row(Buf* buf, unsigned row, unsigned pos) {
-    screen_clearrow(row);
-    for (unsigned x = 0; x < NumCols;) {
-        Rune r = buf_get(buf, pos++);
-        x += screen_setcell(row, x, r);
-        if (buf_iseol(buf, pos-1)) break;
-    }
-}
-
 static unsigned prev_screen_line(Buf* buf, unsigned bol, unsigned off) {
     unsigned pos = bol;
     while (true) {
@@ -163,8 +165,7 @@ static void sync_view(Buf* buf, unsigned csr) {
 void screen_update(Buf* buf, unsigned csr, unsigned* csrx, unsigned* csry) {
     /* scroll the view and reflow the screen lines */
     sync_view(buf, csr);
-    if (buf->insert_mode)
-        screen_reflow(buf);
+    screen_reflow(buf);
     /* find the cursor on the new screen */
     for (unsigned y = 0; y < NumRows; y++) {
         unsigned start = Rows[y]->off;
index 0c037bc71284bfb4060601582ed76830a36129e9..fd409e3867a51f977134aeee8ba1fcf43edffdc9 100644 (file)
@@ -5,6 +5,8 @@
 Buf Buffer;
 unsigned CursorPos;
 unsigned TargetCol;
+unsigned DotBeg;
+unsigned DotEnd;
 enum ColorScheme ColorBase;
 
 int main(int argc, char** argv) {
diff --git a/xedit.c b/xedit.c
index d45d6de94623c0e6a17f718ba1e1c5c15735c5cb..96f965bf9fa9ef0efebae7d1bfb210077788c762 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -132,7 +132,7 @@ void font_find(XftGlyphFontSpec* spec, Rune rune) {
 }
 
 int font_makespecs(XftGlyphFontSpec* specs, const UGlyph* glyphs, int len, int x, int y) {
-    int winx = x * Fonts.base.width, winy = y * Fonts.base.height;
+    int winx = x * Fonts.base.width, winy = y * Fonts.base.ascent;
     int numspecs = 0;
     for (int i = 0, xp = winx, yp = winy + Fonts.base.ascent; i < len;) {
         font_find(&(specs[numspecs]), glyphs[i].rune);
@@ -277,7 +277,7 @@ static MouseEvent* getmouse(XEvent* e) {
         event.type   = MouseMove;
         event.button = MOUSE_NONE;
         event.x      = e->xmotion.x / Fonts.base.width;
-        event.y      = e->xmotion.y / (Fonts.base.ascent + Fonts.base.descent);
+        event.y      = e->xmotion.y / Fonts.base.height;
     } else {
         event.type = (e->type = ButtonPress ? MouseDown : MouseUp);
         /* set the button id */
@@ -290,7 +290,7 @@ static MouseEvent* getmouse(XEvent* e) {
             default:      event.button = MOUSE_NONE;      break;
         }
         event.x = e->xbutton.x / Fonts.base.width;
-        event.y = e->xbutton.y / (Fonts.base.ascent + Fonts.base.descent);
+        event.y = e->xbutton.y / Fonts.base.height;
     }
     return &event;
 }
@@ -319,13 +319,46 @@ static void handle_event(XEvent* e) {
 void draw_runes(unsigned x, unsigned y, XftColor* fg, XftColor* bg, UGlyph* glyphs, size_t rlen) {
     (void)bg;
     XftGlyphFontSpec specs[rlen];
-    size_t nspecs = font_makespecs(specs, glyphs, rlen, x, y);
-    XftDrawGlyphFontSpec(X.xft, fg, specs, nspecs);
+    while (rlen) {
+        size_t nspecs = font_makespecs(specs, glyphs, rlen, x, y);
+        XftDrawGlyphFontSpec(X.xft, fg, specs, nspecs);
+        rlen -= nspecs;
+    }
+}
+
+void draw_glyphs(unsigned x, unsigned y, UGlyph* glyphs, size_t rlen, size_t ncols) {
+    XftGlyphFontSpec specs[rlen];
+    int i = 0;
+    while (rlen) {
+        int numspecs = 0;
+        int attr = glyphs[i].attr;
+        while (i < ncols && glyphs[i].attr == attr) {
+            font_find(&(specs[numspecs]), glyphs[i].rune);
+            specs[numspecs].x = x;
+            specs[numspecs].y = y - Fonts.base.descent;
+            x += Fonts.base.width;
+            numspecs++;
+            i++;
+            /* skip over null chars which mark multi column runes */
+            for (; i < ncols && !glyphs[i].rune; i++)
+                x += Fonts.base.width;
+        }
+        /* Draw the glyphs with the proper colors */
+        uint8_t bg = attr >> 8;
+        uint8_t fg = attr & 0xFF;
+        if (bg != CLR_BASE03)
+            XftDrawRect(X.xft, clr(bg), specs[0].x, y-Fonts.base.height, x-specs[0].x, Fonts.base.height);
+        XftDrawGlyphFontSpec(X.xft, clr(fg), specs, numspecs);
+        rlen -= numspecs;
+    }
+}
+
+void draw_row(unsigned x, unsigned y, Row* row) {
+    draw_glyphs(x, y, row->cols, row->rlen, row->len);
 }
 
 static void draw_status(XftColor* fg, unsigned ncols) {
-    UGlyph glyphs[ncols];
-    UGlyph* status = glyphs;
+    UGlyph glyphs[ncols], *status = glyphs;
     (status++)->rune = (Buffer.charset == BINARY ? 'B' : 'U');
     (status++)->rune = (Buffer.crlf ? 'C' : 'N');
     (status++)->rune = (Buffer.modified ? '*' : ' ');
@@ -336,11 +369,25 @@ static void draw_status(XftColor* fg, unsigned ncols) {
     draw_runes(0, 0, fg, NULL, glyphs, status - glyphs);
 }
 
+static void draw_cursor(unsigned csrx, unsigned csry) {
+    unsigned rwidth;
+    UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth);
+    csrrune->attr = (CLR_BASE3 << 8 | CLR_BASE03);
+    if (Buffer.insert_mode) {
+        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
+    } else {
+        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height);
+        draw_glyphs(csrx * Fonts.base.width, (csry+2) * Fonts.base.height, csrrune, 1, rwidth);
+    }
+}
+
 static void redraw(void) {
+    uint32_t start = getmillis();
     /* draw the background colors */
     XftDrawRect(X.xft, BKGCLR, 0, 0, X.width, X.height);
     XftDrawRect(X.xft, GTRCLR, 79 * Fonts.base.width, 0, Fonts.base.width, X.height);
-    XftDrawRect(X.xft, TXTCLR, 0, 0, X.width, Fonts.base.height);
+    XftDrawRect(X.xft, clr(CLR_BASE02), 0, 0, X.width, Fonts.base.height);
+    XftDrawRect(X.xft, clr(CLR_BASE01), 0, Fonts.base.height, X.width, 1);
 
     /* update the screen buffer and retrieve cursor coordinates */
     unsigned csrx, csry;
@@ -349,25 +396,19 @@ static void redraw(void) {
     /* flush the screen buffer */
     unsigned nrows, ncols;
     screen_getsize(&nrows, &ncols);
-    draw_status(BKGCLR, ncols);
+    draw_status(clr(CLR_BASE2), ncols);
     for (unsigned y = 0; y < nrows; y++) {
         Row* row = screen_getrow(y);
-        draw_runes(0, y+1, TXTCLR, NULL, row->cols, row->len);
+        draw_glyphs(0, (y+2) * Fonts.base.height, row->cols, row->rlen, row->len);
     }
 
     /* Place cursor on screen */
-    unsigned rwidth;
-    UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth);
-    if (Buffer.insert_mode) {
-        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, 1, Fonts.base.height);
-    } else {
-        XftDrawRect(X.xft, CSRCLR, csrx * Fonts.base.width, (csry+1) * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height);
-        draw_runes(csrx, csry+1, BKGCLR, NULL, csrrune, 1);
-    }
+    draw_cursor(csrx, csry);
 
     /* flush pixels to the screen */
     XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0);
     XFlush(X.display);
+    printf("refresh: %u\n", getmillis() - start);
 }
 
 int main(int argc, char** argv) {