2009-01-24 Chris Allegretta <chrisa@asty.org>
+ * 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.
/* 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. */
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;
* 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;
}
/* 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;
#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;
/* 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) {
}
}
+/* 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 */
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. */
/* 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;
/* 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;
* 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) {
* 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 &&
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;
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;
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
#ifdef ENABLE_COLOR
- newnode->colors = NULL;
- newnode->colorclean = FALSE;
+ newnode->multiswatching = NULL;
#endif
return newnode;
dst->next = src->next;
dst->prev = src->prev;
dst->lineno = src->lineno;
+#ifdef ENABLE_COLOR
+ dst->multiswatching = NULL;
+#endif
return dst;
}
if (fileptr->data != NULL)
free(fileptr->data);
+#ifdef ENABLE_COLOR
+ if (fileptr->multiswatching)
+ free(fileptr->multiswatching);
+#endif
+
free(fileptr);
}
kbinput = (int *)nrealloc(kbinput, kbinput_len *
sizeof(int));
kbinput[kbinput_len - 1] = input;
+
}
}
#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;
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;
openfile->placewewant = xplustabs();
+
+ reset_multis(openfile->current);
if (do_refresh)
edit_refresh();
else
/* 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 {
/* 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;
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;
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
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
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);
/* 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
endsyntax->extensions = NULL;
endsyntax->headers = NULL;
endsyntax->next = NULL;
+ endsyntax->nmultis = 0;
#ifdef DEBUG
fprintf(stderr, "Starting a new syntax type: \"%s\"\n", nameptr);
/* 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++;
}
}
}
* 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)
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. */
}
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
/* 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) {
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;
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
/* We painted to the end of the line, so
* don't bother checking any more
* starts. */
+ fileptr->multiswatching[tmpcolor->id] = TRUE;
break;
}
}
/* 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. */
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. */
/* 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. */
* 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 ||