]> git.mdlowis.com Git - projs/tide.git/commitdiff
Added a gutter and logic for displaying line numbers. Next step is to calculate and...
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 3 Jun 2017 02:00:53 +0000 (22:00 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 3 Jun 2017 02:00:53 +0000 (22:00 -0400)
config.h
inc/edit.h
lib/buf.c
lib/view.c
lib/win.c
tide.c

index f48a0f1ae33e1d92f65e3f5bb8ff634ef24b6338..6589ee2bb3d5a21f669e66221d4c8b3e7762406b 100644 (file)
--- a/config.h
+++ b/config.h
@@ -2,9 +2,10 @@
 extern char *FontString, *DefaultTags;
 extern unsigned int ColorPalette[16];
 extern char *ShellCmd[], *SedCmd[], *PickFileCmd[], *PickTagCmd[], *OpenCmd[];
-extern int CLR_NormalText, CLR_SelectedText, CLR_TagsBkg, CLR_EditBkg,
-           CLR_HorBorder, CLR_VerBorder, CLR_Ruler, CLR_ScrollBkg, CLR_ThumbBkg,
-           CLR_Cursor;
+extern int CLR_NormalText, CLR_GutterText, CLR_SelectedText, CLR_TagsBkg,
+           CLR_EditBkg, CLR_HorBorder, CLR_VerBorder, CLR_Ruler, CLR_ScrollBkg,
+           CLR_ThumbBkg, CLR_Cursor;
+extern int LineNumbers;
 
 /* OS-Specific Config
  ******************************************************************************/
@@ -81,6 +82,7 @@ unsigned int ColorPalette[16] = {
 
 #define COLOR_PAIR(bg, fg) (((bg) << 8) | (fg))
 int CLR_NormalText   = COLOR_PAIR(0,4);
+int CLR_GutterText   = COLOR_PAIR(0,3);
 int CLR_SelectedText = COLOR_PAIR(4,0);
 int CLR_TagsBkg      = 1; // Background color for the tags region
 int CLR_EditBkg      = 0; // Background color for the edit region
@@ -91,5 +93,7 @@ int CLR_VerBorder    = 2; // Vertical border color
 int CLR_Ruler        = 1; // Ruler color
 int CLR_Cursor       = 7; // Cursor color
 
+int LineNumbers = 1;
+
 #undef INCLUDE_DEFS
 #endif
index 65e2f2b1435746336db71f2cdc063b89205b16e8..4bdfc1c94b5b0bdca3eb818791e7437dababe6a2 100644 (file)
@@ -58,6 +58,7 @@ typedef struct buf {
     bool copy_indent;     /* copy the indent level from the previous line on new lines */
     uint transid;         /* tracks the last used transaction id for log entries */
     void (*errfn)(char*); /* callback for error messages */
+    size_t nlines;
 } Buf;
 
 /* cursor/selection representation */
index 35737b06573de5661efb68faf38e56f2b8b9170f..cfd20faf86e891756b3c081a1a658acfb764758d 100644 (file)
--- a/lib/buf.c
+++ b/lib/buf.c
@@ -45,6 +45,7 @@ void buf_init(Buf* buf, void (*errfn)(char*)) {
     buf->undo        = NULL;
     buf->redo        = NULL;
     buf->errfn       = errfn;
+    buf->nlines      = 0;
     assert(buf->bufstart);
 }
 
@@ -143,7 +144,9 @@ size_t buf_end(Buf* buf) {
 }
 
 size_t buf_insert(Buf* buf, bool fmt, size_t off, Rune rune) {
+    bool is_eol = (rune == '\n' || rune == RUNE_CRLF);
     buf->modified = true;
+    if (is_eol) buf->nlines++;
     if (fmt && buf->expand_tabs && rune == '\t') {
         size_t n = (TabWidth - ((off - buf_bol(buf, off)) % TabWidth));
         log_insert(buf, &(buf->undo), off, off+n);
@@ -155,7 +158,7 @@ size_t buf_insert(Buf* buf, bool fmt, size_t off, Rune rune) {
             off += n;
         }
     }
-    if (fmt && buf->copy_indent && (rune == '\n' || rune == RUNE_CRLF)) {
+    if (fmt && buf->copy_indent && is_eol) {
         size_t beg = buf_bol(buf, off-1), end = beg;
         for (; end < buf_end(buf) && (' ' == buf_get(buf, end) || '\t' == buf_get(buf, end)); end++);
         for (; beg < end; beg++)
@@ -170,6 +173,8 @@ size_t buf_delete(Buf* buf, size_t beg, size_t end) {
     log_clear(&(buf->redo));
     for (size_t i = end-beg; i > 0; i--) {
         Rune r = buf_get(buf, beg);
+        bool is_eol = (r == '\n' || r == RUNE_CRLF);
+        if (is_eol) buf->nlines--;
         log_delete(buf, &(buf->undo), beg, &r, 1);
         delete(buf, beg);
     }
@@ -298,12 +303,13 @@ void buf_getblock(Buf* buf, Rune first, Rune last, Sel* sel) {
 size_t buf_byrune(Buf* buf, size_t pos, int count) {
     int move = (count < 0 ? -1 : 1);
     count *= move; // remove the sign if there is one
-    for (; count > 0; count--)
+    for (; count > 0; count--) {
         if (move < 0) {
             if (pos > 0) pos--;
         } else {
             if (pos < buf_end(buf)) pos++;
         }
+    }
     return pos;
 }
 
@@ -404,8 +410,6 @@ void buf_lastins(Buf* buf, size_t* beg, size_t* end) {
     *beg = opbeg, *end = opend;
 }
 
-/*****************************************************************************/
-
 size_t buf_setln(Buf* buf, size_t line) {
     size_t off = 0;
     while (line > 1 && off < buf_end(buf))
index e8cd06f33dacd9aed3052d266c91f22034642183..1c86c58026c6fbc5ee366b16e7e534278971362f 100644 (file)
@@ -434,7 +434,9 @@ static void move_selection(View* view, bool extsel, Sel* sel, int move, movefn_t
             sel->end = buf_setcol(&(view->buffer), sel->end, sel->col);
         if (!extsel) sel->beg = sel->end;
     }
-    sel->col = buf_getcol(&(view->buffer), sel->end);
+    /* only update column if not moving vertically */
+    if (bything != buf_byline)
+        sel->col = buf_getcol(&(view->buffer), sel->end);
 }
 
 static void select_context(View* view, bool (*isword)(Rune), Sel* sel) {
index 8b9fe69a648a4c1d92ad33b2f32f01a5bb609fe6..484f89b527a2dcf01c40b399a1a76a1d3d7da858 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -12,6 +12,7 @@ static void onmousedrag(int state, int x, int y);
 static void onmousebtn(int btn, bool pressed, int x, int y);
 static void onwheelup(WinRegion id, bool pressed, size_t row, size_t col);
 static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col);
+static void draw_line_num(size_t x, size_t y, size_t gcols, size_t num);
 static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols);
 static WinRegion getregion(size_t x, size_t y);
 
@@ -141,6 +142,18 @@ void win_setscroll(double offset, double visible) {
     ScrollVisible = visible;
 }
 
+static size_t gutter_cols(void) {
+    size_t len = 1, lines = win_buf(EDIT)->nlines;
+    while (LineNumbers && lines > 9)
+        lines /= 10, len++;
+    return len;
+}
+
+static size_t gutter_size(void) {
+    if (!LineNumbers) return 0;
+    return (gutter_cols() * x11_font_width(Font)) + (LineNumbers ? 5 : 0);
+}
+
 static void layout(int width, int height) {
     size_t fheight = x11_font_height(Font);
     size_t fwidth  = x11_font_width(Font);
@@ -176,7 +189,7 @@ static void layout(int width, int height) {
     Regions[SCROLL].width  = 5 + fwidth;
 
     /* Place the edit region relative to tags */
-    Regions[EDIT].x      = 3 + Regions[SCROLL].width;
+    Regions[EDIT].x      = 3 + Regions[SCROLL].width + gutter_size();
     Regions[EDIT].y      = 5 + Regions[TAGS].y + Regions[TAGS].height;
     Regions[EDIT].height = (height - Regions[EDIT].y - 5);
     Regions[EDIT].width  = width - Regions[SCROLL].width - 5;
@@ -184,9 +197,12 @@ static void layout(int width, int height) {
 }
 
 static void onredraw(int width, int height) {
+    static uint64_t maxtime = 0;
     size_t fheight = x11_font_height(Font);
     size_t fwidth  = x11_font_width(Font);
 
+    uint64_t start = getmillis();
+
     layout(width, height);
     onupdate(); // Let the user program update the status and other content
     view_update(win_view(STATUS), &(Regions[STATUS].csrx), &(Regions[STATUS].csry));
@@ -199,9 +215,17 @@ static void onredraw(int width, int height) {
         x11_draw_rect((i == TAGS ? CLR_TagsBkg : CLR_EditBkg),
             0, Regions[i].y - 3, width, Regions[i].height + 8);
         x11_draw_rect(CLR_HorBorder, 0, Regions[i].y - 3, width, 1);
-        if ((i == EDIT) && (Ruler != 0))
-            x11_draw_rect(CLR_Ruler, (Ruler+2) * fwidth, Regions[i].y-2, 1, Regions[i].height+7);
+
+        if (i == EDIT) {
+            if (Ruler)
+                x11_draw_rect(CLR_Ruler, (Ruler+2) * fwidth, Regions[i].y-2, 1, Regions[i].height+7);
+            if (LineNumbers)
+                x11_draw_rect(CLR_Ruler, Regions[SCROLL].width, Regions[SCROLL].y-2, gutter_size(), Regions[SCROLL].height+7);
+        }
+
+        size_t gcols = gutter_cols();
         for (size_t y = 0; y < view->nrows; y++) {
+            draw_line_num(Regions[i].x - (gcols * fwidth) - 5, Regions[i].y + ((y+1) * fheight), gcols, (y % 2 ? 123 : 45));
             Row* row = view_getrow(view, y);
             draw_glyphs(Regions[i].x, Regions[i].y + ((y+1) * fheight), row->cols, row->rlen, row->len);
         }
@@ -231,6 +255,15 @@ static void onredraw(int width, int height) {
         size_t y = Regions[Focused].y + (Regions[Focused].csry * fheight) + (fheight/2);
         x11_mouse_set(x, y);
     }
+
+    printf("lines: %llu\n", win_buf(EDIT)->nlines);
+
+    uint64_t stop = getmillis();
+    uint64_t elapsed = stop-start;
+    if (elapsed > maxtime) {
+        printf("%llu\n", elapsed);
+        maxtime = elapsed;
+    }
 }
 
 static void oninput(int mods, Rune key) {
@@ -323,6 +356,23 @@ static void onwheeldn(WinRegion id, bool pressed, size_t row, size_t col) {
     view_scroll(win_view(id), +ScrollLines);
 }
 
+static void draw_line_num(size_t x, size_t y, size_t gcols, size_t num) {
+    UGlyph glyphs[gcols];
+    if (LineNumbers) {
+        printf("cols: %lu\n", gcols);
+        for (int i = gcols-1; i >= 0; i--) {
+            glyphs[i].attr = CLR_GutterText;
+            if (num > 0) {
+                glyphs[i].rune = ((num % 10) + '0');
+                num /= 10;
+            } else {
+                glyphs[i].rune = ' ';
+            }
+        }
+        draw_glyphs(x, y, glyphs, gcols, gcols);
+    }
+}
+
 static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols) {
     XGlyphSpec specs[rlen];
     size_t i = 0;
diff --git a/tide.c b/tide.c
index 061f16cdeba0ecae6aa6394377af762c03f95ac5..71c6553ae7b05031621112bf44fd097ba4e20898 100644 (file)
--- a/tide.c
+++ b/tide.c
@@ -237,6 +237,10 @@ static void tag_redo(void) {
     view_redo(win_view(EDIT));
 }
 
+static void tag_lnnum(void) {
+    LineNumbers = !LineNumbers;
+}
+
 static void search(void) {
     char* str;
     SearchDir *= (x11_keymodsset(ModShift) ? UP : DOWN);
@@ -413,6 +417,7 @@ static Tag Builtins[] = {
     { .tag = "SaveAs",    .action.arg   = saveas    },
     { .tag = "Tabs",      .action.noarg = tabs      },
     { .tag = "Undo",      .action.noarg = tag_undo  },
+    { .tag = "LineNums",  .action.noarg = tag_lnnum },
     { .tag = NULL,        .action.noarg = NULL      }
 };