]> git.mdlowis.com Git - projs/tide.git/commitdiff
Fixed display and selection of multi-column unicode characters. Also cleaned up tab...
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 15 Oct 2016 21:18:42 +0000 (17:18 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 15 Oct 2016 21:18:42 +0000 (17:18 -0400)
edit.h
screen.c
xedit.c

diff --git a/edit.h b/edit.h
index d964836193180696bb8a357e8a3afb26b879efe6..fe4830363fa53c4215597815c71b2e600b6389a2 100644 (file)
--- a/edit.h
+++ b/edit.h
@@ -192,18 +192,15 @@ typedef struct {
     UGlyph cols[]; /* row data */
 } Row;
 
-void screen_reflow(Buf* buf);
 void screen_update(Buf* buf, unsigned crsr, unsigned* csrx, unsigned* csry);
 unsigned screen_getoff(Buf* buf, unsigned pos, unsigned row, unsigned col);
 void screen_setsize(Buf* buf, unsigned nrows, unsigned ncols);
 void screen_getsize(unsigned* nrows, unsigned* ncols);
-void screen_clear(void);
 Row* screen_getrow(unsigned row);
 void screen_clearrow(unsigned row);
-void screen_setrowoff(unsigned row, unsigned off);
 unsigned screen_setcell(unsigned row, unsigned col, Rune r);
-UGlyph* screen_getcell(unsigned row, unsigned col);
 void screen_status(char* fmt, ...);
+UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth);
 
 /* Color Scheme Handling
  *****************************************************************************/
index 326a54e415cfc1f7637cb07f709efb519e95f571..b9952e29a6d3235a3ee84e79ee9d4542a1877d5e 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -1,14 +1,15 @@
 #include "edit.h"
+#include <wchar.h>
 
 static unsigned NumRows = 0;
 static unsigned NumCols = 0;
 static Row** Rows;
 
-void screen_reflow(Buf* buf) {
+static void screen_reflow(Buf* buf) {
     unsigned pos = Rows[1]->off;
     for (unsigned y = 1; y < NumRows; y++) {
         screen_clearrow(y);
-        screen_setrowoff(y, pos);
+        screen_getrow(y)->off = pos;
         for (unsigned x = 0; x < NumCols;) {
             Rune r = buf_get(buf, pos++);
             x += screen_setcell(y,x,r);
@@ -42,15 +43,13 @@ unsigned screen_getoff(Buf* buf, unsigned pos, unsigned row, unsigned col) {
     if (col > scrrow->len) {
         pos = (scrrow->off + scrrow->rlen - 1);
     } else {
-        for (unsigned x = 0; x < col;) {
-            Rune r = buf_get(buf,pos++);
-            if (r == '\n')
-                break;
-            else if (r == '\t')
-                x += (TabWidth - (x % TabWidth));
-            else
-                x += 1;
-        }
+        /* multi column runes are followed by \0 slots so if we clicked on a \0
+           slot, slide backwards to the real rune. */
+        for (; !scrrow->cols[col].rune && col > 0; col--);
+        /* now lets count the number of runes up to the one we clicked on */
+        for (unsigned i = 0; i < col; i++)
+            if (scrrow->cols[i].rune)
+                pos++;
     }
     if (pos >= buf_end(buf))
         return buf_end(buf)-1;
@@ -61,11 +60,6 @@ void screen_getsize(unsigned* nrows, unsigned* ncols) {
     *nrows = NumRows, *ncols = NumCols;
 }
 
-void screen_clear(void) {
-    for (unsigned i = 0; i < NumRows; i++)
-        screen_clearrow(i);
-}
-
 Row* screen_getrow(unsigned row) {
     return (row < NumRows ? Rows[row] : NULL);
 }
@@ -79,32 +73,39 @@ void screen_clearrow(unsigned row) {
     scrrow->len  = 0;
 }
 
-void screen_setrowoff(unsigned row, unsigned off) {
-    screen_getrow(row)->off = off;
+static int runewidth(unsigned col, Rune r) {
+    if (r == '\t') return (TabWidth - (col % TabWidth));
+    int width = wcwidth(r);
+    if (width < 0) width = 1;
+    return width;
 }
 
 unsigned screen_setcell(unsigned row, unsigned col, 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 */
-    unsigned ncols = 1;
-    if (r == '\t') {
+    if (r == '\t' || r == '\n' || r == '\r')
         scrrow->cols[col].rune = ' ';
-        ncols = (TabWidth - (col % TabWidth));
-    } else if (r != '\n') {
+    else
         scrrow->cols[col].rune = r;
-    }
     /* Update lengths */
     scrrow->rlen += 1;
+    for (int i = 1; i < ncols; i++)
+        scrrow->cols[col+i].rune = '\0';
     if ((col + ncols) > scrrow->len)
         scrrow->len = col + ncols;
     return ncols;
 }
 
-UGlyph* screen_getcell(unsigned row, unsigned col) {
+UGlyph* screen_getglyph(unsigned row, unsigned col, unsigned* scrwidth) {
     if (row >= NumRows || col >= NumCols) return 0;
     Row* scrrow = screen_getrow(row);
-    return &(scrrow->cols[col]);
+    UGlyph* glyph = &(scrrow->cols[col]);
+    *scrwidth = 1;
+    for (col++; !scrrow->cols[col].rune; col++)
+        *scrwidth += 1;
+    return glyph;
 }
 
 static void fill_row(Buf* buf, unsigned row, unsigned pos) {
@@ -119,11 +120,9 @@ 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) {
-        unsigned x = 0;
-        for (; x < NumCols && (pos + x) < off; x++) {
-            Rune r = buf_get(buf, pos+x);
-            x += (r == '\t' ? (TabWidth - (x % TabWidth)) : 1);
-        }
+        unsigned x;
+        for (x = 0; x < NumCols && (pos + x) < off; x++)
+            x += runewidth(x, buf_get(buf, pos+x));
         if ((pos + x) >= off) break;
         pos += x;
     }
@@ -185,10 +184,7 @@ void screen_update(Buf* buf, unsigned csr, unsigned* csrx, unsigned* csry) {
                     *csry = y, *csrx = x;
                     break;
                 }
-                if (buf_get(buf,pos++) == '\t')
-                    x += (TabWidth - (x % TabWidth));
-                else
-                    x += 1;
+                x += runewidth(x, buf_get(buf,pos++));
             }
             break;
         }
diff --git a/xedit.c b/xedit.c
index 04bd59b51f9ad28a84b0b5950939c4b2962fa651..d83c28c6a6bfbe1a099e162669e34e5043de4b49 100644 (file)
--- a/xedit.c
+++ b/xedit.c
@@ -127,14 +127,16 @@ 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 numspecs = 0;
-    for (int i = 0, xp = winx, yp = winy + Fonts.base.ascent; i < len; ++i) {
-        if (!glyphs[i].rune) continue;
+    for (int i = 0, xp = winx, yp = winy + Fonts.base.ascent; i < len;) {
         font_find(&(specs[numspecs]), glyphs[i].rune);
-        int runewidth = wcwidth(glyphs[i].rune) * Fonts.base.width;
         specs[numspecs].x = xp;
         specs[numspecs].y = yp;
-        xp += runewidth;
+        xp += Fonts.base.width;
         numspecs++;
+        i++;
+        /* skip over null chars which mark multi column runes */
+        for (; i < len && !glyphs[i].rune; i++)
+            xp += Fonts.base.width;
     }
     return numspecs;
 }
@@ -144,9 +146,9 @@ int font_makespecs(XftGlyphFontSpec* specs, const UGlyph* glyphs, int len, int x
 static XftColor xftcolor(enum ColorId cid) {
     Color c = Palette[cid][ColorBase];
     XftColor xc;
-    xc.color.red   = ((c & 0x00FF0000) >> 8);
-    xc.color.green = ((c & 0x0000FF00));
-    xc.color.blue  = ((c & 0x000000FF) << 8);
+    xc.color.red   = 0xFF | ((c & 0x00FF0000) >> 8);
+    xc.color.green = 0xFF | ((c & 0x0000FF00));
+    xc.color.blue  = 0xFF | ((c & 0x000000FF) << 8);
     xc.color.alpha = UINT16_MAX;
     XftColorAllocValue(X.display, X.visual, X.colormap, &xc.color, &xc);
     return xc;
@@ -338,12 +340,12 @@ static void redraw(void) {
     }
 
     /* Place cursor on screen */
-    UGlyph* csrrune = screen_getcell(csry,csrx);
+    unsigned rwidth;
+    UGlyph* csrrune = screen_getglyph(csry, csrx, &rwidth);
     if (Buffer.insert_mode) {
         XftDrawRect(X.xft, &csrclr, csrx * Fonts.base.width, csry * Fonts.base.height, 2, Fonts.base.height);
     } else {
-        unsigned width = ('\t' == buf_get(&Buffer, CursorPos) ? (TabWidth - (csrx % TabWidth)) : 1);
-        XftDrawRect(X.xft, &csrclr, csrx * Fonts.base.width, csry * Fonts.base.height, width * Fonts.base.width, Fonts.base.height);
+        XftDrawRect(X.xft, &csrclr, csrx * Fonts.base.width, csry * Fonts.base.height, rwidth * Fonts.base.width, Fonts.base.height);
         draw_runes(csrx, csry, &bkgclr, NULL, csrrune, 1);
     }