2009-02-02 Chris Allegretta <chrisa@asty.org>

* 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
master
Chris Allegretta 2009-02-03 05:05:58 +00:00
parent ecc245ccca
commit 364763f4d1
5 changed files with 136 additions and 27 deletions

View 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 */

View 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) {

View 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);

View 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;

View 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;
short md = fileptr->multidata[tmpcolor->id];
fileptr->multiswatching[tmpcolor->id] = FALSE; /* until we find out otherwise */
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;
}
}