From d47d8cd450f32b9cdbf9225237bd39632548fc6b Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Sun, 25 Jan 2009 07:25:17 +0000 Subject: [PATCH] * First pass at some caching of caching color info. Right now it's only for multi-line regexes but this may not be enough to increase performance. git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4351 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 2 ++ src/color.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- src/files.c | 4 ++++ src/move.c | 12 ++++++------ src/nano.c | 26 ++++++++++++++++++++++---- src/nano.h | 9 +++++++-- src/proto.h | 7 ++++--- src/rcfile.c | 6 ++++++ src/winio.c | 30 ++++++++++++++++++++++-------- 9 files changed, 115 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3af262b0..86fd49b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,6 @@ 2009-01-24 Chris Allegretta + * First pass at some caching of caching color info. Right now it's only for + multi-line regexes but this may not be enough to increase performance. * Add interruptability to search functions. New functions enable_nodelay and disable_nodelay and changes to the routines to handle checking for pending searches. Fixes Savnnah bug 24946: Need interrrupt for search. diff --git a/src/color.c b/src/color.c index 353a5baf..d59c3d5d 100644 --- a/src/color.c +++ b/src/color.c @@ -105,11 +105,13 @@ void color_init(void) /* Update the color information based on the current filename. */ void color_update(void) { - const syntaxtype *tmpsyntax; + syntaxtype *tmpsyntax; + syntaxtype *defsyntax = NULL; colortype *tmpcolor, *defcolor = NULL; assert(openfile != NULL); + openfile->syntax = NULL; openfile->colorstrings = NULL; /* If we specified a syntax override string, use it. */ @@ -121,8 +123,10 @@ void color_update(void) for (tmpsyntax = syntaxes; tmpsyntax != NULL; tmpsyntax = tmpsyntax->next) { - if (strcmp(tmpsyntax->desc, syntaxstr) == 0) + if (strcmp(tmpsyntax->desc, syntaxstr) == 0) { + openfile->syntax = tmpsyntax; openfile->colorstrings = tmpsyntax->color; + } if (openfile->colorstrings != NULL) break; @@ -141,6 +145,7 @@ void color_update(void) * extensions, which we've checked for elsewhere. Skip over * it here, but keep track of its color regexes. */ if (strcmp(tmpsyntax->desc, "default") == 0) { + defsyntax = tmpsyntax; defcolor = tmpsyntax->color; continue; } @@ -159,8 +164,10 @@ void color_update(void) /* Set colorstrings if we matched the extension * regex. */ if (regexec(e->ext, openfile->filename, 0, NULL, - 0) == 0) + 0) == 0) { + openfile->syntax = tmpsyntax; openfile->colorstrings = tmpsyntax->color; + } if (openfile->colorstrings != NULL) break; @@ -200,8 +207,10 @@ void color_update(void) #ifdef DEBUG fprintf(stderr, "Comparing header regex \"%s\" to fileage \"%s\"...\n", e->ext_regex, openfile->fileage->data); #endif - if (regexec(e->ext, openfile->fileage->data, 0, NULL, 0) == 0) + if (regexec(e->ext, openfile->fileage->data, 0, NULL, 0) == 0) { + openfile->syntax = tmpsyntax; openfile->colorstrings = tmpsyntax->color; + } if (openfile->colorstrings != NULL) break; @@ -221,8 +230,10 @@ void color_update(void) /* If we didn't get a syntax based on the file extension, and we * have a default syntax, use it. */ - if (openfile->colorstrings == NULL && defcolor != NULL) + if (openfile->colorstrings == NULL && defcolor != NULL) { + openfile->syntax = defsyntax; openfile->colorstrings = defcolor; + } for (tmpcolor = openfile->colorstrings; tmpcolor != NULL; tmpcolor = tmpcolor->next) { @@ -243,4 +254,30 @@ void color_update(void) } } +/* Reset multi line strings around a filestruct ptr, trying to be smart about stopping */ +void reset_multis(filestruct *fileptr) +{ + int i; + filestruct *oof; + + for (i = 0; i < openfile->syntax->nmultis; i++) { + for (oof = fileptr->next; oof != NULL; oof = oof->next) { + if (oof->multiswatching == NULL) + continue; + if (oof->multiswatching[i] == FALSE) + oof->multiswatching[i] = TRUE; + else + break; + } + for (oof = fileptr->prev; oof != NULL; oof = oof->prev) { + if (oof->multiswatching == NULL) + continue; + if (oof->multiswatching[i] == FALSE) + oof->multiswatching[i] = TRUE; + else + break; + } + fileptr->multiswatching[i] = TRUE; + } +} #endif /* ENABLE_COLOR */ diff --git a/src/files.c b/src/files.c index 08c7d3a4..10c3a798 100644 --- a/src/files.c +++ b/src/files.c @@ -311,6 +311,10 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool fileptr->data[buf_len - 1] = '\0'; #endif +#ifdef ENABLE_COLOR + fileptr->multiswatching = NULL; +#endif + if (*first_line_ins) { /* Special case: We're inserting with the cursor on the first * line. */ diff --git a/src/move.c b/src/move.c index 05892e03..531a48cb 100644 --- a/src/move.c +++ b/src/move.c @@ -29,7 +29,7 @@ /* Move to the first line of the file. */ void do_first_line(void) { - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; size_t pww_save = openfile->placewewant; openfile->current = openfile->fileage; @@ -42,7 +42,7 @@ void do_first_line(void) /* Move to the last line of the file. */ void do_last_line(void) { - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; size_t pww_save = openfile->placewewant; openfile->current = openfile->filebot; @@ -130,7 +130,7 @@ void do_page_down(void) * afterwards. */ void do_para_begin(bool allow_update) { - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; const size_t pww_save = openfile->placewewant; if (openfile->current != openfile->fileage) { @@ -162,7 +162,7 @@ void do_para_begin_void(void) * paragraph or isn't in a paragraph. */ void do_para_end(bool allow_update) { - const filestruct *const current_save = openfile->current; + filestruct *const current_save = openfile->current; const size_t pww_save = openfile->placewewant; while (openfile->current != openfile->filebot && @@ -206,7 +206,7 @@ void do_para_end_void(void) bool do_next_word(bool allow_punct, bool allow_update) { size_t pww_save = openfile->placewewant; - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; char *char_mb; int char_mb_len; bool end_line = FALSE, started_on_word = FALSE; @@ -301,7 +301,7 @@ void do_next_word_void(void) bool do_prev_word(bool allow_punct, bool allow_update) { size_t pww_save = openfile->placewewant; - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; char *char_mb; int char_mb_len; bool begin_line = FALSE, started_on_word = FALSE; diff --git a/src/nano.c b/src/nano.c index 8fa7f8eb..1eff99e0 100644 --- a/src/nano.c +++ b/src/nano.c @@ -68,8 +68,7 @@ filestruct *make_new_node(filestruct *prevnode) newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1; #ifdef ENABLE_COLOR - newnode->colors = NULL; - newnode->colorclean = FALSE; + newnode->multiswatching = NULL; #endif return newnode; @@ -88,6 +87,9 @@ filestruct *copy_node(const filestruct *src) dst->next = src->next; dst->prev = src->prev; dst->lineno = src->lineno; +#ifdef ENABLE_COLOR + dst->multiswatching = NULL; +#endif return dst; } @@ -124,6 +126,11 @@ void delete_node(filestruct *fileptr) if (fileptr->data != NULL) free(fileptr->data); +#ifdef ENABLE_COLOR + if (fileptr->multiswatching) + free(fileptr->multiswatching); +#endif + free(fileptr); } @@ -1444,6 +1451,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int)); kbinput[kbinput_len - 1] = input; + } } @@ -1510,9 +1518,17 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool #ifndef NANO_TINY if (s->scfunc == DO_TOGGLE) do_toggle(s->toggle); - else + else { #endif iso_me_harder_funcmap(s->scfunc); +#ifdef ENABLE_COLOR + if (!f->viewok && openfile->syntax != NULL + && openfile->current->multiswatching && openfile->syntax->nmultis > 0) { + reset_multis(openfile->current); + edit_refresh(); + } +#endif + } } *finished = TRUE; break; @@ -1551,7 +1567,7 @@ int do_mouse(void) bool sameline; /* Did they click on the line with the cursor? If they * clicked on the cursor, we set the mark. */ - const filestruct *current_save = openfile->current; + filestruct *current_save = openfile->current; size_t current_x_save = openfile->current_x; size_t pww_save = openfile->placewewant; @@ -1688,6 +1704,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) openfile->placewewant = xplustabs(); + + reset_multis(openfile->current); if (do_refresh) edit_refresh(); else diff --git a/src/nano.h b/src/nano.h index 7accb104..203cb402 100644 --- a/src/nano.h +++ b/src/nano.h @@ -196,6 +196,8 @@ typedef struct colortype { /* The compiled end (if any) of the regex string. */ struct colortype *next; /* Next set of colors. */ + int id; + /* basic id for assigning to lines later */ } colortype; typedef struct exttype { @@ -216,6 +218,8 @@ typedef struct syntaxtype { /* Regexes to match on the 'header' (1st line) of the file */ colortype *color; /* The colors used in this syntax. */ + int nmultis; + /* How many multi line strings this syntax has */ struct syntaxtype *next; /* Next syntax. */ } syntaxtype; @@ -233,8 +237,7 @@ typedef struct filestruct { struct filestruct *prev; /* Previous node. */ #ifdef ENABLE_COLOR - colortype **colors; /* Will be a series of pointers to the colorstrings we're painting */ - bool colorclean; /* Did we do something to the line which necessitates recalculating the colors */ + bool *multiswatching; /* Array of which multi-line regexes apply to this line */ #endif } filestruct; @@ -328,6 +331,8 @@ typedef struct openfilestruct { undo_type last_action; #endif #ifdef ENABLE_COLOR + syntaxtype *syntax; + /* The syntax struct for this file, if any */ colortype *colorstrings; /* The current file's associated colors. */ #endif diff --git a/src/proto.h b/src/proto.h index ec9b5f4b..628f90b1 100644 --- a/src/proto.h +++ b/src/proto.h @@ -542,6 +542,7 @@ void parse_syntax(char *ptr); void parse_include(char *ptr); short color_to_short(const char *colorname, bool *bright); void parse_colors(char *ptr, bool icase); +void reset_multis(filestruct *fileptr); #endif void parse_rcfile(FILE *rcstream #ifdef ENABLE_COLOR @@ -759,13 +760,13 @@ void statusbar(const char *msg, ...); void bottombars(int menu); void onekey(const char *keystroke, const char *desc, size_t len); void reset_cursor(void); -void edit_draw(const filestruct *fileptr, const char *converted, int +void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start); -void update_line(const filestruct *fileptr, size_t index); +void update_line(filestruct *fileptr, size_t index); bool need_horizontal_update(size_t pww_save); bool need_vertical_update(size_t pww_save); void edit_scroll(scroll_dir direction, ssize_t nlines); -void edit_redraw(const filestruct *old_current, size_t pww_save); +void edit_redraw(filestruct *old_current, size_t pww_save); void edit_refresh(void); void edit_update(update_type location); void total_redraw(void); diff --git a/src/rcfile.c b/src/rcfile.c index 05ba82d9..a12c8014 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -107,6 +107,7 @@ static exttype *endheader = NULL; /* End of header list */ static colortype *endcolor = NULL; /* The end of the color list for the current syntax. */ + #endif /* We have an error in some part of the rcfile. Print the error message @@ -296,6 +297,7 @@ void parse_syntax(char *ptr) endsyntax->extensions = NULL; endsyntax->headers = NULL; endsyntax->next = NULL; + endsyntax->nmultis = 0; #ifdef DEBUG fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr); @@ -716,6 +718,10 @@ void parse_colors(char *ptr, bool icase) /* Save the ending regex string if it's valid. */ newcolor->end_regex = (nregcomp(fgstr, icase ? REG_ICASE : 0)) ? mallocstrcpy(NULL, fgstr) : NULL; + + /* Lame way to skip another static counter */ + newcolor->id = endsyntax->nmultis; + endsyntax->nmultis++; } } } diff --git a/src/winio.c b/src/winio.c index b14dbccd..d0e67781 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2450,7 +2450,7 @@ void reset_cursor(void) * character of this page. That is, the first character of converted * corresponds to character number actual_x(fileptr->data, start) of the * line. */ -void edit_draw(const filestruct *fileptr, const char *converted, int +void edit_draw(filestruct *fileptr, const char *converted, int line, size_t start) { #if !defined(NANO_TINY) || defined(ENABLE_COLOR) @@ -2478,6 +2478,14 @@ void edit_draw(const filestruct *fileptr, const char *converted, int if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) { 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 + && 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 */ + } for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) { int x_start; /* Starting column for mvwaddnstr. Zero-based. */ @@ -2543,7 +2551,7 @@ void edit_draw(const filestruct *fileptr, const char *converted, int } k = startmatch.rm_eo; } - } else { + } else if (fileptr->multiswatching != NULL && fileptr->multiswatching[tmpcolor->id] == TRUE) { /* 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 @@ -2561,6 +2569,8 @@ void edit_draw(const filestruct *fileptr, const char *converted, int /* Where it starts in that line. */ const filestruct *end_line; + fileptr->multiswatching[tmpcolor->id] = FALSE; /* until we find out otherwise */ + while (start_line != NULL && regexec(tmpcolor->start, start_line->data, 1, &startmatch, 0) == REG_NOMATCH) { @@ -2631,7 +2641,7 @@ void edit_draw(const filestruct *fileptr, const char *converted, int endmatch.rm_eo) - start); 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; @@ -2676,6 +2686,9 @@ void edit_draw(const filestruct *fileptr, const char *converted, int mvwaddnstr(edit, line, x_start, converted + index, paintlen); + if (paintlen > 0) + fileptr->multiswatching[tmpcolor->id] = TRUE; + } } else { /* There is no end on this line. But we @@ -2696,6 +2709,7 @@ void edit_draw(const 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; break; } } @@ -2785,7 +2799,7 @@ void edit_draw(const filestruct *fileptr, const char *converted, int /* Just update one line in the edit buffer. This is basically a wrapper * for edit_draw(). The line will be displayed starting with * fileptr->data[index]. Likely arguments are current_x or zero. */ -void update_line(const filestruct *fileptr, size_t index) +void update_line(filestruct *fileptr, size_t index) { int line; /* The line in the edit window that we want to update. */ @@ -2858,7 +2872,7 @@ bool need_vertical_update(size_t pww_save) void edit_scroll(scroll_dir direction, ssize_t nlines) { bool do_redraw = need_vertical_update(0); - const filestruct *foo; + filestruct *foo; ssize_t i; /* Don't bother scrolling less than one line. */ @@ -2953,11 +2967,11 @@ void edit_scroll(scroll_dir direction, ssize_t nlines) /* Update any lines between old_current and current that need to be * updated. Use this if we've moved without changing any text. */ -void edit_redraw(const filestruct *old_current, size_t pww_save) +void edit_redraw(filestruct *old_current, size_t pww_save) { bool do_redraw = need_vertical_update(0) || need_vertical_update(pww_save); - const filestruct *foo = NULL; + filestruct *foo = NULL; /* If either old_current or current is offscreen, scroll the edit * window until it's onscreen and get out. */ @@ -3065,7 +3079,7 @@ void edit_redraw(const filestruct *old_current, size_t pww_save) * if we've moved and changed text. */ void edit_refresh(void) { - const filestruct *foo; + filestruct *foo; int nlines; if (openfile->current->lineno < openfile->edittop->lineno ||