]> git.wh0rd.org Git - nano.git/commitdiff
2009-02-02 Chris Allegretta <chrisa@asty.org>
authorChris Allegretta <chrisa@asty.org>
Tue, 3 Feb 2009 05:05:58 +0000 (05:05 +0000)
committerChris Allegretta <chrisa@asty.org>
Tue, 3 Feb 2009 05:05:58 +0000 (05:05 +0000)
        * New color precalculation code for mult-line regexes.  New function precalc_multicolorinfo(),
          new structure multidata for keeping track of where regexes start/stop.  More
          performance improvements forthcoming.

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4362 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

src/color.c
src/files.c
src/nano.c
src/nano.h
src/winio.c

index 4babe482473b97e19fc6ec57cfea3a32167a249f..deac8b4ec36944c80706aeaa31c8ac9fad1546f3 100644 (file)
@@ -265,22 +265,22 @@ void reset_multis(filestruct *fileptr)
 
     for (i = 0; i < openfile->syntax->nmultis; i++) {
        for (oof = fileptr->next; oof != NULL; oof = oof->next) {
-           if (oof->multiswatching == NULL)
+           if (oof->multidata == NULL)
                continue;
-           if (oof->multiswatching[i] == FALSE)
-               oof->multiswatching[i] = TRUE;
+           if (oof->multidata[i] != 0)
+               oof->multidata[i] = -1;
            else
                break;
        }
        for (oof = fileptr->prev; oof != NULL; oof = oof->prev) {
-           if (oof->multiswatching == NULL)
+           if (oof->multidata == NULL)
                continue;
-           if (oof->multiswatching[i] == FALSE)
-               oof->multiswatching[i] = TRUE;
+           if (oof->multidata[i] == 0)
+               oof->multidata[i] = -1;
            else
                break;
            }
-       fileptr->multiswatching[i] = TRUE;
+       fileptr->multidata[i] = -1;
     }
 }
 #endif /* ENABLE_COLOR */
index 0f599c9c0b467afcfe8a964d78ae4eba7ff224fb..2e95010b99dcb68944298da8efbebefbd09bec4e 100644 (file)
@@ -312,7 +312,7 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
 #endif
 
 #ifdef ENABLE_COLOR
-       fileptr->multiswatching = NULL;
+       fileptr->multidata = NULL;
 #endif
 
     if (*first_line_ins) {
index cdf302e9c6698c18909db9c5975543f9b61ac220..72cd925e4b3aeb2bff9a69fd942567878d11ba1b 100644 (file)
@@ -68,7 +68,7 @@ filestruct *make_new_node(filestruct *prevnode)
     newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
 
 #ifdef ENABLE_COLOR
-    newnode->multiswatching = NULL;
+    newnode->multidata = NULL;
 #endif
 
     return newnode;
@@ -88,7 +88,7 @@ filestruct *copy_node(const filestruct *src)
     dst->prev = src->prev;
     dst->lineno = src->lineno;
 #ifdef ENABLE_COLOR
-    dst->multiswatching = NULL;
+    dst->multidata = NULL;
 #endif
 
     return dst;
@@ -127,8 +127,8 @@ void delete_node(filestruct *fileptr)
        free(fileptr->data);
 
 #ifdef ENABLE_COLOR
-    if (fileptr->multiswatching)
-       free(fileptr->multiswatching);
+    if (fileptr->multidata)
+       free(fileptr->multidata);
 #endif
 
     free(fileptr);
@@ -369,7 +369,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
     openfile->filebot = openfile->fileage;
 
 #ifdef ENABLE_COLOR
-    openfile->fileage->multiswatching = NULL;
+    openfile->fileage->multidata = NULL;
 #endif
 
     /* Restore the current line and cursor position.  If the mark begins
@@ -1596,7 +1596,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
                                iso_me_harder_funcmap(s->scfunc);
 #ifdef ENABLE_COLOR
                                if (!f->viewok && openfile->syntax != NULL 
-                                       && openfile->current->multiswatching && openfile->syntax->nmultis > 0) {
+                                       && openfile->current->multidata && openfile->syntax->nmultis > 0) {
                                    reset_multis(openfile->current);
                                    edit_refresh();
                                }
@@ -1675,6 +1675,87 @@ int do_mouse(void)
 }
 #endif /* !DISABLE_MOUSE */
 
+#ifdef ENABLE_COLOR
+/* Precalculate the multi-line start and end regex info so we can speed up
+   rendering (with any hope at all...) */
+void precalc_multicolorinfo(void)
+{
+    if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
+       const colortype *tmpcolor = openfile->colorstrings;
+       regmatch_t startmatch, endmatch;
+       filestruct *fileptr, *endptr;
+       time_t last_check = time(NULL), cur_check = 0;
+
+       /* Let us get keypresses to see if the user is trying to
+          start editing.  We may want to throw up a statusbar
+          message before starting this later if it takes
+          too long to do this routine.  For now silently
+          abort if they hit a key */
+       nodelay(edit, FALSE);
+
+       for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
+
+           /* If it's not a multi-line regex, amscray */
+           if (tmpcolor->end == NULL)
+               continue;
+
+           for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
+               int startx = 0;
+
+               if (!fileptr->multidata)
+                   fileptr->multidata = nmalloc(openfile->syntax->nmultis * sizeof(short));
+
+               if ((cur_check = time(NULL)) - last_check > 1) {
+                   last_check = cur_check;
+                   if (wgetch(edit) != ERR)
+                       goto precalc_cleanup;
+               }
+
+               fileptr->multidata[tmpcolor->id] = CNONE;
+               while (regexec(tmpcolor->start, &fileptr->data[startx], 1, &startmatch, 0)  == 0) {
+                   /* Look for end and start marking how many lines are encompassed
+                      whcih should speed up rendering later */
+                    startx += startmatch.rm_eo;
+
+                   /* Look on this line first for end */
+                   if (regexec(tmpcolor->end, &fileptr->data[startx], 1, &endmatch, 0)  == 0) {
+                       startx += endmatch.rm_eo;
+                       fileptr->multidata[tmpcolor->id] |= CSTARTENDHERE;
+                       continue;
+                   }
+
+                   /* Nice, we didn't find the end regex on this line.  Let's start looking for it */
+                   for (endptr = fileptr->next; endptr != NULL; endptr = endptr->next) {
+
+                       /* Check for keyboard input  again */
+                       if ((cur_check = time(NULL)) - last_check > 1) {
+                           last_check = cur_check;
+                           if (wgetch(edit) != ERR)
+                               goto precalc_cleanup;
+                       }
+                       if (regexec(tmpcolor->end, &endptr->data[startx], 1, &endmatch, 0) == 0)
+                          break;
+                   }
+
+                   if (endptr == NULL)
+                       break;
+
+                   /* We found it, we found it, la la la la la.  Mark all the
+                       lines in between and the ends properly */
+                   fileptr->multidata[tmpcolor->id] |= CENDAFTER;
+                   for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) {
+                       fileptr->multidata[tmpcolor->id] = CWHOLELINE;
+                   }
+                   endptr->multidata[tmpcolor->id] |= CBEGINBEFORE;
+               }
+           }
+       }
+    }
+precalc_cleanup:
+    nodelay(edit, FALSE);
+}
+#endif /* ENABLE_COLOR */
+
 /* The user typed output_len multibyte characters.  Add them to the edit
  * buffer, filtering out all ASCII control characters if allow_cntrls is
  * TRUE. */
@@ -2373,6 +2454,11 @@ int main(int argc, char **argv)
     fprintf(stderr, "Main: top and bottom win\n");
 #endif
 
+#ifdef ENABLE_COLOR
+    if (openfile->syntax && openfile->syntax->nmultis > 0)
+       precalc_multicolorinfo();
+#endif
+
     if (startline > 1 || startcol > 1)
        do_gotolinecolumn(startline, startcol, FALSE, FALSE, FALSE,
                FALSE);
index 5613db60ea1437cc5104d28182c2e72b0da8634f..e4beb8dc686ec96ccfd4182137d57d2bbbf168d1 100644 (file)
@@ -223,6 +223,20 @@ typedef struct syntaxtype {
     struct syntaxtype *next;
        /* Next syntax. */
 } syntaxtype;
+
+#define CNONE          (1<<0)
+       /* Yay, regex doesn't apply to this line at all! */
+#define CBEGINBEFORE   (1<<1)
+       /* regex starts on an earlier line, ends on this one */
+#define CENDAFTER      (1<<2)
+       /* regex sraers on this line and ends on a later one */
+#define CWHOLELINE     (1<<3)
+       /* whole line engulfed by the regex  start < me, end > me */
+#define CSTARTENDHERE  (1<<4)
+       /* regex starts and ends within this line */
+#define CWTF           (1<<5)
+       /* Something else */
+
 #endif /* ENABLE_COLOR */
 
 
@@ -237,7 +251,7 @@ typedef struct filestruct {
     struct filestruct *prev;
        /* Previous node. */
 #ifdef ENABLE_COLOR
-    bool *multiswatching;              /* Array of which multi-line regexes apply to this line */
+    short *multidata;          /* Array of which multi-line regexes apply to this line */
 #endif
 } filestruct;
 
index d0e67781072349aca9b3469dbb95e04651887df5..90f9e91f78125ae20e49741724d37c93befd511e 100644 (file)
@@ -2479,12 +2479,12 @@ void edit_draw(filestruct *fileptr, const char *converted, int
        const colortype *tmpcolor = openfile->colorstrings;
 
        /* Set up multi-line color data for this line if it's not yet calculated  */
-        if (fileptr->multiswatching == NULL && openfile->syntax
+        if (fileptr->multidata == NULL && openfile->syntax
                && openfile->syntax->nmultis > 0) {
            int i;
-           fileptr->multiswatching = nmalloc(openfile->syntax->nmultis * sizeof(bool));
-            for (i = 0; i < openfile->syntax->nmultis; i++) 
-               fileptr->multiswatching[i] = TRUE;      /* Assue this applies until we know otherwise */
+           fileptr->multidata = nmalloc(openfile->syntax->nmultis * sizeof(short));
+            for (i = 0; i < openfile->syntax->nmultis; i++)
+               fileptr->multidata[i] = -1;     /* Assue this applies until we know otherwise */
        }
        for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
            int x_start;
@@ -2551,7 +2551,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
                    }
                    k = startmatch.rm_eo;
                }
-           } else if (fileptr->multiswatching != NULL && fileptr->multiswatching[tmpcolor->id] == TRUE) {
+           } else if (fileptr->multidata != NULL && fileptr->multidata[tmpcolor->id] != 0) {
                /* This is a multi-line regex.  There are two steps.
                 * First, we have to see if the beginning of the line is
                 * colored by a start on an earlier line, and an end on
@@ -2568,8 +2568,16 @@ void edit_draw(filestruct *fileptr, const char *converted, int
                regoff_t start_col;
                    /* Where it starts in that line. */
                const filestruct *end_line;
-
-               fileptr->multiswatching[tmpcolor->id] = FALSE; /* until we find out otherwise */
+               short md = fileptr->multidata[tmpcolor->id];
+
+               if (md == -1)
+                   fileptr->multidata[tmpcolor->id] = 0; /* until we find out otherwise */
+               else if (md == CNONE)
+                   continue;
+               else if (md == CWHOLELINE) {
+                   mvwaddnstr(edit, line, 0, converted, -1);
+                   continue;
+               }
 
                while (start_line != NULL && regexec(tmpcolor->start,
                        start_line->data, 1, &startmatch, 0) ==
@@ -2633,15 +2641,16 @@ void edit_draw(filestruct *fileptr, const char *converted, int
                     * expanded location of the end of the match minus
                     * the expanded location of the beginning of the
                     * page. */
-                   if (end_line != fileptr)
+                   if (end_line != fileptr) {
                        paintlen = -1;
-                   else
+                       fileptr->multidata[tmpcolor->id] = CWHOLELINE;
+                   } else {
                        paintlen = actual_x(converted,
                                strnlenpt(fileptr->data,
                                endmatch.rm_eo) - start);
-
+                       fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
+                   }
                    mvwaddnstr(edit, line, 0, converted, paintlen);
-                   fileptr->multiswatching[tmpcolor->id] = TRUE;
   step_two:
                    /* Second step, we look for starts on this line. */
                    start_col = 0;
@@ -2687,7 +2696,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
                                mvwaddnstr(edit, line, x_start,
                                        converted + index, paintlen);
                                if (paintlen > 0)
-                                   fileptr->multiswatching[tmpcolor->id] = TRUE;
+                                   fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
 
                            }
                        } else {
@@ -2709,7 +2718,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
                                /* We painted to the end of the line, so
                                 * don't bother checking any more
                                 * starts. */
-                               fileptr->multiswatching[tmpcolor->id] = TRUE;
+                               fileptr->multidata[tmpcolor->id] = CENDAFTER;
                                break;
                            }
                        }