2001-05-05 19:01:42 +04:00
|
|
|
/**************************************************************************
|
2016-08-29 18:10:49 +03:00
|
|
|
* color.c -- This file is part of GNU nano. *
|
2001-05-05 19:01:42 +04:00
|
|
|
* *
|
2021-01-11 16:21:03 +03:00
|
|
|
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
2020-11-30 14:01:47 +03:00
|
|
|
* Copyright (C) 2014-2017, 2020 Benno Schulenberg *
|
2016-08-29 16:14:18 +03:00
|
|
|
* *
|
2016-08-29 18:10:49 +03:00
|
|
|
* GNU nano is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published *
|
|
|
|
* by the Free Software Foundation, either version 3 of the License, *
|
|
|
|
* or (at your option) any later version. *
|
2001-05-05 19:01:42 +04:00
|
|
|
* *
|
2016-08-29 18:10:49 +03:00
|
|
|
* GNU nano is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
|
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
|
|
* See the GNU General Public License for more details. *
|
2001-05-05 19:01:42 +04:00
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
2016-08-29 18:10:49 +03:00
|
|
|
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
2001-05-05 19:01:42 +04:00
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
2020-06-20 13:09:31 +03:00
|
|
|
#include "prototypes.h"
|
2001-05-05 19:01:42 +04:00
|
|
|
|
2019-10-13 19:51:15 +03:00
|
|
|
#ifdef ENABLE_COLOR
|
|
|
|
|
2011-02-13 07:23:10 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#ifdef HAVE_MAGIC_H
|
|
|
|
#include <magic.h>
|
|
|
|
#endif
|
2017-08-06 14:32:44 +03:00
|
|
|
#include <string.h>
|
2001-05-05 19:01:42 +04:00
|
|
|
|
2020-06-13 14:34:03 +03:00
|
|
|
static bool defaults_allowed = FALSE;
|
|
|
|
/* Whether ncurses accepts -1 to mean "default color". */
|
2020-06-13 14:24:52 +03:00
|
|
|
|
2020-04-28 17:43:11 +03:00
|
|
|
/* Initialize the color pairs for nano's interface. */
|
|
|
|
void set_interface_colorpairs(void)
|
2001-05-05 19:01:42 +04:00
|
|
|
{
|
2014-05-03 22:24:45 +04:00
|
|
|
#ifdef HAVE_USE_DEFAULT_COLORS
|
2020-06-13 14:34:03 +03:00
|
|
|
/* Ask ncurses to allow -1 to mean "default color". */
|
|
|
|
defaults_allowed = (use_default_colors() == OK);
|
2014-05-03 22:24:45 +04:00
|
|
|
#endif
|
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* Initialize the color pairs for nano's interface elements. */
|
2020-01-28 12:20:17 +03:00
|
|
|
for (size_t index = 0; index < NUMBER_OF_ELEMENTS; index++) {
|
|
|
|
colortype *combo = color_combo[index];
|
2017-12-29 21:27:33 +03:00
|
|
|
|
2018-01-15 18:07:24 +03:00
|
|
|
if (combo != NULL) {
|
2020-06-13 14:50:23 +03:00
|
|
|
if (!defaults_allowed) {
|
2020-06-17 17:54:48 +03:00
|
|
|
if (combo->fg == THE_DEFAULT)
|
2020-06-13 14:50:23 +03:00
|
|
|
combo->fg = COLOR_WHITE;
|
2020-06-17 17:54:48 +03:00
|
|
|
if (combo->bg == THE_DEFAULT)
|
2020-06-13 14:50:23 +03:00
|
|
|
combo->bg = COLOR_BLACK;
|
|
|
|
}
|
2020-01-28 12:20:17 +03:00
|
|
|
init_pair(index + 1, combo->fg, combo->bg);
|
2020-11-15 12:11:54 +03:00
|
|
|
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
|
2017-12-29 21:27:33 +03:00
|
|
|
} else {
|
2020-08-28 19:40:10 +03:00
|
|
|
if (index == FUNCTION_TAG || index == SCROLL_BAR)
|
2020-01-28 12:20:17 +03:00
|
|
|
interface_color_pair[index] = A_NORMAL;
|
|
|
|
else if (index == GUIDE_STRIPE)
|
|
|
|
interface_color_pair[index] = A_REVERSE;
|
2021-02-02 16:50:45 +03:00
|
|
|
else if (index == HIGHLIGHTED) {
|
2021-02-15 13:29:23 +03:00
|
|
|
init_pair(index + 1, COLOR_BLACK, COLOR_YELLOW + (COLORS > 15 ? 8 : 0));
|
2021-02-02 16:50:45 +03:00
|
|
|
interface_color_pair[index] = COLOR_PAIR(index + 1);
|
|
|
|
} else if (index == PROMPT_BAR)
|
2020-12-06 17:49:35 +03:00
|
|
|
interface_color_pair[index] = interface_color_pair[TITLE_BAR];
|
2020-01-28 12:20:17 +03:00
|
|
|
else if (index == ERROR_MESSAGE) {
|
|
|
|
init_pair(index + 1, COLOR_WHITE, COLOR_RED);
|
2020-11-15 12:11:54 +03:00
|
|
|
interface_color_pair[index] = COLOR_PAIR(index + 1) | A_BOLD;
|
2018-02-20 11:50:54 +03:00
|
|
|
} else
|
2020-01-28 12:20:17 +03:00
|
|
|
interface_color_pair[index] = hilite_attribute;
|
2017-12-29 21:27:33 +03:00
|
|
|
}
|
2014-05-03 22:24:45 +04:00
|
|
|
|
2020-01-28 12:20:17 +03:00
|
|
|
free(color_combo[index]);
|
2017-12-29 21:27:33 +03:00
|
|
|
}
|
2002-09-27 18:21:59 +04:00
|
|
|
}
|
2001-11-29 05:42:27 +03:00
|
|
|
|
2020-06-13 18:14:57 +03:00
|
|
|
/* Assign a pair number to each of the foreground/background color combinations
|
|
|
|
* in the given syntax, giving identical combinations the same number. */
|
|
|
|
void set_syntax_colorpairs(syntaxtype *sntx)
|
|
|
|
{
|
|
|
|
short number = NUMBER_OF_ELEMENTS;
|
|
|
|
colortype *older;
|
|
|
|
|
|
|
|
for (colortype *ink = sntx->color; ink != NULL; ink = ink->next) {
|
|
|
|
if (!defaults_allowed) {
|
2020-06-17 17:54:48 +03:00
|
|
|
if (ink->fg == THE_DEFAULT)
|
2020-06-13 18:14:57 +03:00
|
|
|
ink->fg = COLOR_WHITE;
|
2020-06-17 17:54:48 +03:00
|
|
|
if (ink->bg == THE_DEFAULT)
|
2020-06-13 18:14:57 +03:00
|
|
|
ink->bg = COLOR_BLACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
older = sntx->color;
|
|
|
|
|
|
|
|
while (older != ink && (older->fg != ink->fg || older->bg != ink->bg))
|
|
|
|
older = older->next;
|
|
|
|
|
|
|
|
ink->pairnum = (older != ink) ? older->pairnum : ++number;
|
|
|
|
|
2020-11-15 12:11:54 +03:00
|
|
|
ink->attributes |= COLOR_PAIR(ink->pairnum);
|
2020-06-13 18:14:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-28 17:38:27 +03:00
|
|
|
/* Initialize the color pairs for the current syntax. */
|
|
|
|
void prepare_palette(void)
|
2002-09-27 18:21:59 +04:00
|
|
|
{
|
2020-06-13 15:10:25 +03:00
|
|
|
short number = NUMBER_OF_ELEMENTS;
|
2015-12-18 13:41:09 +03:00
|
|
|
|
2020-06-13 15:10:25 +03:00
|
|
|
/* For each unique pair number, tell ncurses the combination of colors. */
|
|
|
|
for (colortype *ink = openfile->syntax->color; ink != NULL; ink = ink->next)
|
|
|
|
if (ink->pairnum > number) {
|
|
|
|
init_pair(ink->pairnum, ink->fg, ink->bg);
|
|
|
|
number = ink->pairnum;
|
|
|
|
}
|
2017-04-27 22:42:36 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
have_palette = TRUE;
|
2001-05-05 19:01:42 +04:00
|
|
|
}
|
|
|
|
|
2016-02-26 19:37:23 +03:00
|
|
|
/* Try to match the given shibboleth string with one of the regexes in
|
|
|
|
* the list starting at head. Return TRUE upon success. */
|
|
|
|
bool found_in_list(regexlisttype *head, const char *shibboleth)
|
|
|
|
{
|
2017-12-29 21:27:33 +03:00
|
|
|
regexlisttype *item;
|
|
|
|
regex_t rgx;
|
2016-02-26 19:37:23 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
for (item = head; item != NULL; item = item->next) {
|
2021-01-21 14:18:44 +03:00
|
|
|
regcomp(&rgx, item->full_regex, NANO_REG_EXTENDED | REG_NOSUB);
|
2016-02-26 19:37:23 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) {
|
|
|
|
regfree(&rgx);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2016-03-04 17:53:45 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
regfree(&rgx);
|
|
|
|
}
|
2016-02-26 19:37:23 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
return FALSE;
|
2016-02-26 19:37:23 +03:00
|
|
|
}
|
|
|
|
|
2020-04-28 17:32:04 +03:00
|
|
|
/* Find a syntax that applies to the current buffer, based upon filename
|
|
|
|
* or buffer content, and load and prime this syntax when needed. */
|
|
|
|
void find_and_prime_applicable_syntax(void)
|
2002-05-04 07:47:33 +04:00
|
|
|
{
|
2020-02-21 19:02:24 +03:00
|
|
|
syntaxtype *sntx = NULL;
|
2011-02-13 07:23:10 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If the rcfiles were not read, or contained no syntaxes, get out. */
|
|
|
|
if (syntaxes == NULL)
|
|
|
|
return;
|
2014-06-30 21:47:07 +04:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If we specified a syntax-override string, use it. */
|
|
|
|
if (syntaxstr != NULL) {
|
|
|
|
/* An override of "none" is like having no syntax at all. */
|
|
|
|
if (strcmp(syntaxstr, "none") == 0)
|
|
|
|
return;
|
2005-08-01 08:59:34 +04:00
|
|
|
|
2020-02-21 19:07:11 +03:00
|
|
|
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
2020-02-21 19:02:24 +03:00
|
|
|
if (strcmp(sntx->name, syntaxstr) == 0)
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
2015-11-24 14:42:19 +03:00
|
|
|
|
2020-02-21 19:02:24 +03:00
|
|
|
if (sntx == NULL && !inhelp)
|
2017-12-29 21:27:33 +03:00
|
|
|
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
|
2015-04-28 22:18:38 +03:00
|
|
|
}
|
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If no syntax-override string was specified, or it didn't match,
|
|
|
|
* try finding a syntax based on the filename (extension). */
|
2020-02-21 19:02:24 +03:00
|
|
|
if (sntx == NULL && !inhelp) {
|
2019-09-17 14:31:09 +03:00
|
|
|
char *fullname = get_full_path(openfile->filename);
|
2015-04-28 22:18:38 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
if (fullname == NULL)
|
|
|
|
fullname = mallocstrcpy(fullname, openfile->filename);
|
2011-02-13 07:23:10 +03:00
|
|
|
|
2020-02-21 19:07:11 +03:00
|
|
|
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
2020-02-21 19:02:24 +03:00
|
|
|
if (found_in_list(sntx->extensions, fullname))
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
2015-04-28 22:18:38 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
free(fullname);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the filename didn't match anything, try the first line. */
|
2020-02-21 19:02:24 +03:00
|
|
|
if (sntx == NULL && !inhelp) {
|
2020-02-21 19:07:11 +03:00
|
|
|
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
2020-02-21 19:02:24 +03:00
|
|
|
if (found_in_list(sntx->headers, openfile->filetop->data))
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
2005-07-14 00:18:46 +04:00
|
|
|
}
|
2008-09-22 03:02:30 +04:00
|
|
|
|
2014-05-14 14:09:42 +04:00
|
|
|
#ifdef HAVE_LIBMAGIC
|
2020-09-21 10:23:37 +03:00
|
|
|
/* If we still don't have an answer, try using magic (when requested). */
|
|
|
|
if (sntx == NULL && !inhelp && ISSET(USE_MAGIC)) {
|
2017-12-29 21:27:33 +03:00
|
|
|
struct stat fileinfo;
|
|
|
|
magic_t cookie = NULL;
|
|
|
|
const char *magicstring = NULL;
|
|
|
|
|
|
|
|
if (stat(openfile->filename, &fileinfo) == 0) {
|
|
|
|
/* Open the magic database and get a diagnosis of the file. */
|
|
|
|
cookie = magic_open(MAGIC_SYMLINK |
|
2014-05-14 14:29:55 +04:00
|
|
|
#ifdef DEBUG
|
2017-12-29 21:27:33 +03:00
|
|
|
MAGIC_DEBUG | MAGIC_CHECK |
|
2014-05-14 14:29:55 +04:00
|
|
|
#endif
|
2017-12-29 21:27:33 +03:00
|
|
|
MAGIC_ERROR);
|
|
|
|
if (cookie == NULL || magic_load(cookie, NULL) < 0)
|
|
|
|
statusline(ALERT, _("magic_load() failed: %s"), strerror(errno));
|
|
|
|
else {
|
|
|
|
magicstring = magic_file(cookie, openfile->filename);
|
|
|
|
if (magicstring == NULL)
|
|
|
|
statusline(ALERT, _("magic_file(%s) failed: %s"),
|
|
|
|
openfile->filename, magic_error(cookie));
|
|
|
|
}
|
|
|
|
}
|
2014-05-14 14:29:55 +04:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* Now try and find a syntax that matches the magic string. */
|
|
|
|
if (magicstring != NULL) {
|
2020-02-21 19:07:11 +03:00
|
|
|
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
2020-02-21 19:02:24 +03:00
|
|
|
if (found_in_list(sntx->magics, magicstring))
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
|
|
|
}
|
2016-03-12 12:18:50 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
if (stat(openfile->filename, &fileinfo) == 0)
|
|
|
|
magic_close(cookie);
|
|
|
|
}
|
2016-03-12 12:18:50 +03:00
|
|
|
#endif /* HAVE_LIBMAGIC */
|
2005-07-14 00:18:46 +04:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If nothing at all matched, see if there is a default syntax. */
|
2020-02-21 19:02:24 +03:00
|
|
|
if (sntx == NULL && !inhelp) {
|
2020-02-21 19:07:11 +03:00
|
|
|
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
2020-02-21 19:02:24 +03:00
|
|
|
if (strcmp(sntx->name, "default") == 0)
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
2016-02-26 19:08:21 +03:00
|
|
|
}
|
2005-08-01 08:23:29 +04:00
|
|
|
|
2019-05-14 03:01:59 +03:00
|
|
|
/* When the syntax isn't loaded yet, parse it and initialize its colors. */
|
2020-02-21 19:02:24 +03:00
|
|
|
if (sntx != NULL && sntx->filename != NULL) {
|
|
|
|
parse_one_include(sntx->filename, sntx);
|
|
|
|
set_syntax_colorpairs(sntx);
|
2019-05-14 03:01:59 +03:00
|
|
|
}
|
|
|
|
|
2020-02-21 19:02:24 +03:00
|
|
|
openfile->syntax = sntx;
|
2002-05-04 07:47:33 +04:00
|
|
|
}
|
|
|
|
|
2017-02-12 22:49:40 +03:00
|
|
|
/* Determine whether the matches of multiline regexes are still the same,
|
|
|
|
* and if not, schedule a screen refresh, so things will be repainted. */
|
2019-03-21 19:08:52 +03:00
|
|
|
void check_the_multis(linestruct *line)
|
2009-02-06 06:41:02 +03:00
|
|
|
{
|
2017-12-29 21:27:33 +03:00
|
|
|
const colortype *ink;
|
|
|
|
bool astart, anend;
|
|
|
|
regmatch_t startmatch, endmatch;
|
2018-01-18 23:32:34 +03:00
|
|
|
char *afterstart;
|
2017-12-29 21:27:33 +03:00
|
|
|
|
|
|
|
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
|
|
|
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
|
|
|
return;
|
|
|
|
|
2021-01-29 11:53:39 +03:00
|
|
|
if (line->multidata == NULL) {
|
|
|
|
refresh_needed = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
2019-06-23 12:37:38 +03:00
|
|
|
|
2020-05-01 13:38:02 +03:00
|
|
|
for (ink = openfile->syntax->color; ink != NULL; ink = ink->next) {
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If it's not a multiline regex, skip. */
|
|
|
|
if (ink->end == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0);
|
2018-01-18 23:32:34 +03:00
|
|
|
afterstart = line->data + (astart ? startmatch.rm_eo : 0);
|
|
|
|
anend = (regexec(ink->end, afterstart, 1, &endmatch, 0) == 0);
|
2017-12-29 21:27:33 +03:00
|
|
|
|
|
|
|
/* Check whether the multidata still matches the current situation. */
|
2021-01-29 12:58:09 +03:00
|
|
|
if (line->multidata[ink->id] & (NOTHING|WHOLELINE)) {
|
2017-12-29 21:27:33 +03:00
|
|
|
if (!astart && !anend)
|
|
|
|
continue;
|
2021-01-28 18:11:57 +03:00
|
|
|
} else if (line->multidata[ink->id] == JUSTONTHIS) {
|
2017-12-29 21:27:33 +03:00
|
|
|
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
|
|
|
|
continue;
|
2021-01-28 18:11:57 +03:00
|
|
|
} else if (line->multidata[ink->id] == STARTSHERE) {
|
2017-12-29 21:27:33 +03:00
|
|
|
if (astart && !anend)
|
|
|
|
continue;
|
2021-01-29 12:58:09 +03:00
|
|
|
} else if (line->multidata[ink->id] == ENDSHERE) {
|
|
|
|
if (!astart && anend)
|
|
|
|
continue;
|
2017-12-29 21:27:33 +03:00
|
|
|
}
|
2009-02-06 06:41:02 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
/* There is a mismatch, so something changed: repaint. */
|
|
|
|
refresh_needed = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
2009-01-25 10:25:17 +03:00
|
|
|
}
|
2014-04-04 15:59:03 +04:00
|
|
|
|
2015-12-22 19:51:00 +03:00
|
|
|
/* Precalculate the multi-line start and end regex info so we can
|
|
|
|
* speed up rendering (with any hope at all...). */
|
|
|
|
void precalc_multicolorinfo(void)
|
|
|
|
{
|
2017-12-29 21:27:33 +03:00
|
|
|
const colortype *ink;
|
|
|
|
regmatch_t startmatch, endmatch;
|
2019-03-21 19:08:52 +03:00
|
|
|
linestruct *line, *tailline;
|
2015-12-22 19:51:00 +03:00
|
|
|
|
2021-02-03 18:27:51 +03:00
|
|
|
if (!openfile->syntax || openfile->syntax->nmultis == 0 || ISSET(NO_SYNTAX))
|
2017-12-29 21:27:33 +03:00
|
|
|
return;
|
2015-12-22 19:51:00 +03:00
|
|
|
|
2021-01-26 17:41:02 +03:00
|
|
|
//#define TIMEPRECALC 123
|
|
|
|
#ifdef TIMEPRECALC
|
|
|
|
#include <time.h>
|
|
|
|
clock_t start = clock();
|
|
|
|
#endif
|
|
|
|
|
2019-06-23 12:57:27 +03:00
|
|
|
/* For each line, allocate cache space for the multiline-regex info. */
|
|
|
|
for (line = openfile->filetop; line != NULL; line = line->next)
|
2021-01-29 12:30:05 +03:00
|
|
|
line->multidata = nmalloc(openfile->syntax->nmultis * sizeof(short));
|
2019-06-23 12:57:27 +03:00
|
|
|
|
2020-05-01 13:38:02 +03:00
|
|
|
for (ink = openfile->syntax->color; ink != NULL; ink = ink->next) {
|
2017-12-29 21:27:33 +03:00
|
|
|
/* If this is not a multi-line regex, skip it. */
|
|
|
|
if (ink->end == NULL)
|
|
|
|
continue;
|
|
|
|
|
2019-03-21 19:23:49 +03:00
|
|
|
for (line = openfile->filetop; line != NULL; line = line->next) {
|
2017-12-29 21:27:33 +03:00
|
|
|
int index = 0;
|
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
/* Assume nothing applies until proven otherwise below. */
|
2021-01-28 18:11:57 +03:00
|
|
|
line->multidata[ink->id] = NOTHING;
|
2021-01-28 14:11:52 +03:00
|
|
|
|
|
|
|
/* When the line contains a start match, look for an end,
|
|
|
|
* and if found, mark all the lines that are affected. */
|
2017-12-29 21:27:33 +03:00
|
|
|
while (regexec(ink->start, line->data + index, 1,
|
2019-06-09 21:02:58 +03:00
|
|
|
&startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
2017-12-29 21:27:33 +03:00
|
|
|
/* Begin looking for an end match after the start match. */
|
|
|
|
index += startmatch.rm_eo;
|
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
/* If there is an end match on this line, mark the line,
|
|
|
|
* but continue looking for other starts after it. */
|
2017-12-29 21:27:33 +03:00
|
|
|
if (regexec(ink->end, line->data + index, 1,
|
2019-06-09 21:02:58 +03:00
|
|
|
&endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
|
2021-01-28 18:11:57 +03:00
|
|
|
line->multidata[ink->id] = JUSTONTHIS;
|
2021-02-16 18:11:02 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
index += endmatch.rm_eo;
|
2021-02-16 18:11:02 +03:00
|
|
|
|
|
|
|
/* If the total match has zero length, force an advance. */
|
|
|
|
if (startmatch.rm_eo - startmatch.rm_so + endmatch.rm_eo == 0) {
|
|
|
|
/* When at end-of-line, there is no other start. */
|
2017-12-29 21:27:33 +03:00
|
|
|
if (line->data[index] == '\0')
|
|
|
|
break;
|
2019-06-09 20:37:56 +03:00
|
|
|
index = step_right(line->data, index);
|
2017-12-29 21:27:33 +03:00
|
|
|
}
|
2021-02-16 18:11:02 +03:00
|
|
|
|
2017-12-29 21:27:33 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look for an end match on later lines. */
|
|
|
|
tailline = line->next;
|
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
while (tailline && regexec(ink->end, tailline->data,
|
|
|
|
1, &endmatch, 0) != 0)
|
2017-12-29 21:27:33 +03:00
|
|
|
tailline = tailline->next;
|
|
|
|
|
2021-02-06 18:56:22 +03:00
|
|
|
/* When there is no end match, mark relevant lines as such. */
|
2017-12-29 21:27:33 +03:00
|
|
|
if (tailline == NULL) {
|
2021-02-06 18:56:22 +03:00
|
|
|
for (; line->next != NULL; line = line->next)
|
|
|
|
line->multidata[ink->id] = WOULDBE;
|
2021-01-28 18:11:57 +03:00
|
|
|
line->multidata[ink->id] = WOULDBE;
|
2017-12-29 21:27:33 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
/* We found it, we found it, la lala lala. Mark the lines. */
|
2021-01-28 18:11:57 +03:00
|
|
|
line->multidata[ink->id] = STARTSHERE;
|
2017-12-29 21:27:33 +03:00
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
// Note that this also advances the line in the main loop.
|
2019-06-23 12:57:27 +03:00
|
|
|
for (line = line->next; line != tailline; line = line->next)
|
2021-01-28 18:11:57 +03:00
|
|
|
line->multidata[ink->id] = WHOLELINE;
|
2017-12-29 21:27:33 +03:00
|
|
|
|
2021-01-28 18:11:57 +03:00
|
|
|
tailline->multidata[ink->id] = ENDSHERE;
|
2017-12-29 21:27:33 +03:00
|
|
|
|
2021-01-28 14:11:52 +03:00
|
|
|
/* Look for a possible new start after the end match. */
|
2017-12-29 21:27:33 +03:00
|
|
|
index = endmatch.rm_eo;
|
|
|
|
}
|
2017-02-13 00:34:31 +03:00
|
|
|
}
|
2015-12-22 19:51:00 +03:00
|
|
|
}
|
2021-01-26 17:41:02 +03:00
|
|
|
|
|
|
|
#ifdef TIMEPRECALC
|
|
|
|
statusline(INFO, "Precalculation: %.1f ms", 1000 * (double)(clock() - start) / CLOCKS_PER_SEC);
|
|
|
|
napms(1200);
|
|
|
|
#endif
|
2015-12-22 19:51:00 +03:00
|
|
|
}
|
|
|
|
|
2017-11-01 21:45:33 +03:00
|
|
|
#endif /* ENABLE_COLOR */
|