From 364763f4d1e466d0bc4ae8db8656f63f56588ac3 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Tue, 3 Feb 2009 05:05:58 +0000 Subject: [PATCH] 2009-02-02 Chris Allegretta * 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 | 14 ++++---- src/files.c | 2 +- src/nano.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/nano.h | 16 ++++++++- src/winio.c | 35 ++++++++++++------- 5 files changed, 137 insertions(+), 28 deletions(-) diff --git a/src/color.c b/src/color.c index 4babe482..deac8b4e 100644 --- a/src/color.c +++ b/src/color.c @@ -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 */ diff --git a/src/files.c b/src/files.c index 0f599c9c..2e95010b 100644 --- a/src/files.c +++ b/src/files.c @@ -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) { diff --git a/src/nano.c b/src/nano.c index cdf302e9..72cd925e 100644 --- a/src/nano.c +++ b/src/nano.c @@ -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); diff --git a/src/nano.h b/src/nano.h index 5613db60..e4beb8dc 100644 --- a/src/nano.h +++ b/src/nano.h @@ -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; diff --git a/src/winio.c b/src/winio.c index d0e67781..90f9e91f 100644 --- a/src/winio.c +++ b/src/winio.c @@ -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; } } -- 2.39.5