]> git.mdlowis.com Git - projs/tide.git/commitdiff
optimized color scanning so that large files still perform reasonably
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 10 Jun 2017 00:41:40 +0000 (20:41 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 10 Jun 2017 00:41:40 +0000 (20:41 -0400)
inc/edit.h
lib/colors.c
lib/view.c

index 1c699be57e5a04f46ce37512d07a465d58a42f39..a6d959b7230295d881c4b7d5783387eab0cfce73 100644 (file)
@@ -141,7 +141,8 @@ typedef struct SyntaxSpan {
 } SyntaxSpan;
 
 SyntaxDef* colors_find(char* path);
-SyntaxSpan* colors_scan(SyntaxDef* syntax, Buf* buf);
+SyntaxSpan* colors_scan(SyntaxDef* syntax, SyntaxSpan* spans, Buf* buf, size_t beg, size_t end);
+SyntaxSpan* colors_rewind(SyntaxSpan* spans, size_t first);
 
 /* Screen management functions
  *****************************************************************************/
index 5f77de03b594999d0df77960abc161600b438f8e..8fb27bf9f69226d71846ab81638e3a3bfbd0aa6c 100644 (file)
@@ -65,11 +65,10 @@ static SyntaxSpan* mkspan(size_t beg, size_t end, size_t clr, SyntaxSpan* span)
     return newspan;
 }
 
-SyntaxSpan* colors_scan(SyntaxDef* syntax, Buf* buf) {
-    SyntaxSpan* firstspan = NULL;
-    SyntaxSpan* spans = NULL;
-    if (!syntax) return spans;
-    for (size_t end = buf_end(buf), off = 0; off < end; off++) {
+SyntaxSpan* colors_scan(SyntaxDef* syntax, SyntaxSpan* spans, Buf* buf, size_t beg, size_t end) {
+    SyntaxSpan* firstspan = spans;
+    if (!syntax) return firstspan;
+    for (size_t off = beg; off < end; off++) {
         size_t start = off;
         if (matches(buf, &off, syntax->comments.line_beg))
             for (; off < end && !buf_iseol(buf, off); off++);
@@ -82,3 +81,27 @@ SyntaxSpan* colors_scan(SyntaxDef* syntax, Buf* buf) {
     }
     return firstspan;
 }
+
+SyntaxSpan* colors_rewind(SyntaxSpan* spans, size_t first) {
+    /* rewind to the first span that start before visible space */
+    while (spans && spans->beg >= first && spans->prev)
+        spans = spans->prev;
+
+    /* if we're on the first one, setup to return NULL, otherwise return the
+       previous one because we're about to regenerate the current one and
+       everything after it */
+    SyntaxSpan* ret = (spans ? spans->prev : NULL);
+
+    /* ok now free the rest of the list */
+    while (spans) {
+        SyntaxSpan* dead = spans;
+        spans = dead->next;
+        free(dead);
+    }
+
+    /* make sure we clear out the next link */
+    if (ret) ret->next = NULL;
+
+    return ret;
+}
+
index ee1e91d973d9fee5199cf03194ccaccee9fc32c3..5ee56bf174aa7a96e1ec58002c925743bcff5590 100644 (file)
@@ -23,6 +23,7 @@ static unsigned scroll_dn(View* view);
 static void sync_center(View* view, size_t csr);
 static size_t getoffset(View* view, size_t row, size_t col);
 static void sync_line_numbers(View* view);
+static void apply_colors(View* view);
 
 void view_init(View* view, char* file, void (*errfn)(char*)) {
     if (view->nrows) {
@@ -95,40 +96,21 @@ void view_update(View* view, size_t* csrx, size_t* csry) {
         line = buf_getln(&(view->buffer), buf_bol(&(view->buffer), pos));
         view->sync_lines = false;
     }
-
+    /* fill the view and scroll if needed */
     for (size_t y = 0; y < view->nrows; y++)
         pos = fill_row(view, y, pos, &line);
     if (view->sync_needed)
         view_scrollto(view, csr);
     /* locate the cursor if visible */
     find_cursor(view, csrx, csry);
-
-    view->spans = colors_scan(view->syntax, &(view->buffer));
-    SyntaxSpan* curr = view->spans;
-    for (size_t r = 0; curr && r < view->nrows; r++) {
-        Row* row = view->rows[r];
-        size_t off = row->off, col = 0;
-        while (col < row->len) {
-            /* skip irrelevant highlight regions */
-            for (; curr && curr->end < off; curr = curr->next);
-            if (!curr) { r = -1; break; } // Break both loops if we're done
-
-            /* check if we're in the current region */
-            if (curr->beg <= off && off <= curr->end && !(row->cols[col].attr & 0xFF00)) {
-                uint32_t attr = row->cols[col].attr;
-                row->cols[col].attr = (row->cols[col].attr & 0xFF00) | curr->color;
-            }
-            off++, col++;
-            while (col < row->len && row->cols[col].rune == '\0')
-                col++;
-        }
-    }
-
-    while (view->spans) {
-        SyntaxSpan* deadite = view->spans;
-        view->spans = deadite->next;
-        free(deadite);
-    }
+    /* synchronize, scan for, and apply highlighted regions */
+    size_t first = (view->nrows ? view->rows[0]->off : 0),
+           last  = buf_end(&(view->buffer));
+    if (view->nrows)
+        last = view->rows[view->nrows-1]->off + view->rows[view->nrows-1]->rlen;
+    view->spans = colors_rewind(view->spans, first);
+    view->spans = colors_scan(view->syntax, view->spans, &(view->buffer), first, last+1);
+    apply_colors(view);
 }
 
 Row* view_getrow(View* view, size_t row) {
@@ -690,3 +672,26 @@ static void sync_line_numbers(View* view) {
         view->selection.end <= view->rows[0]->off)
         view->sync_lines = true;
 }
+
+static void apply_colors(View* view) {
+    SyntaxSpan* curr = view->spans;
+    for (size_t r = 0; curr && r < view->nrows; r++) {
+        Row* row = view->rows[r];
+        size_t off = row->off, col = 0;
+        while (col < row->len) {
+            /* skip irrelevant highlight regions */
+            for (; curr && curr->end < off; curr = curr->next);
+            if (!curr) { r = -1; break; } // Break both loops if we're done
+
+            /* check if we're in the current region */
+            if (curr->beg <= off && off <= curr->end && !(row->cols[col].attr & 0xFF00)) {
+                uint32_t attr = row->cols[col].attr;
+                row->cols[col].attr = (row->cols[col].attr & 0xFF00) | curr->color;
+            }
+            off++, col++;
+            while (col < row->len && row->cols[col].rune == '\0')
+                col++;
+        }
+    }
+
+}