gambas-source-code/main/lib/eval/c_highlight.c
gambas 8360ee65eb Fix space characters highlighting again.
[GB.EVAL]
* BUG: Fix space characters highlighting again.
2021-02-15 16:15:18 +01:00

316 lines
7.4 KiB
C

/***************************************************************************
c_highlight.c
(c) 2000-2017 Benoît Minisini <g4mba5@gmail.com>
This program 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 2, or (at your option)
any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __C_HIGHLIGHT_CPP
#include "gb_common.h"
#include "main.h"
#include "gb.eval.h"
#include "eval_analyze.h"
#include "c_highlight.h"
static void *_analyze_symbol = 0;
static void *_analyze_type = 0;
static void *_analyze_pos = 0;
static char *_analyze_text = 0;
static char *_purged_line = NULL;
static int get_char_length(unsigned char c)
{
int n = 1;
if (c & 0x80)
{
for (;;)
{
c <<= 1;
if (!(c & 0x80))
break;
n++;
}
}
return n;
}
static char *purge(const char *s, int len_s, bool comment, bool string)
{
char c;
uint i;
int lc, ls;
bool in_comment = FALSE;
char wait = 0;
char *r = NULL;
for (i = 0; i < len_s; i += ls)
{
c = s[i];
ls = lc = get_char_length((unsigned char)c);
switch(wait)
{
case 0:
if (in_comment)
{
if (!comment)
c = ' ', lc = 1;
}
else if (c == '"')
wait = '"';
else if (c == '\'')
in_comment = TRUE;
break;
case '"':
if (c == '"')
wait = 0;
else if (c == '\\')
{
if (string)
{
if (i < len_s)
r = GB.AddChar(r, c);
//r += c;
i++;
c = s[i];
lc = get_char_length((unsigned char)c);
}
else
{
i++;
if (i < len_s)
r = GB.AddChar(r, ' ');
//r += ' ';
c = ' ', lc = 1;
}
}
else
{
if (!string)
c = ' ', lc = 1;
}
break;
}
if (lc == 1)
r = GB.AddChar(r, c);
else
r = GB.AddString(r, &s[i], lc);
}
GB.FreeString(&_purged_line);
_purged_line = r;
return r;
}
static int convState(int state)
{
switch(state)
{
case RT_END: return HIGHLIGHT_NORMAL;
case RT_RESERVED: return HIGHLIGHT_KEYWORD;
case RT_IDENTIFIER: return HIGHLIGHT_SYMBOL;
case RT_CLASS: return HIGHLIGHT_DATATYPE;
case RT_NUMBER: return HIGHLIGHT_NUMBER;
case RT_STRING: return HIGHLIGHT_STRING;
case RT_SUBR: return HIGHLIGHT_SUBR;
case RT_COMMENT: return HIGHLIGHT_COMMENT;
case RT_OPERATOR: return HIGHLIGHT_OPERATOR;
case RT_DATATYPE: return HIGHLIGHT_DATATYPE;
case RT_ERROR: return HIGHLIGHT_ERROR;
case RT_HELP: return HIGHLIGHT_HELP;
case RT_PREPROCESSOR: return HIGHLIGHT_PREPROCESSOR;
case RT_ESCAPE: return HIGHLIGHT_ESCAPE;
case RT_CONSTANT: return HIGHLIGHT_CONSTANT;
case RT_LABEL: return HIGHLIGHT_LABEL;
default: return HIGHLIGHT_NORMAL;
}
}
static void analyze(const char *src, int len_src, bool rewrite, int state)
{
GB_ARRAY garray, tarray, parray;
int i, n, pos, len, p, upos, ulen, l;
char *str;
EVAL_ANALYZE result;
EVAL_analyze(src, len_src, state == HIGHLIGHT_COMMENT ? RT_COMMENT : RT_END, &result, rewrite);
n = 0;
for (i = 0; i < result.len; i++)
{
if (result.color[i].state == RT_END)
break;
if (result.color[i].state != RT_SPACE)
n++;
}
GB.Array.New(&garray, GB_T_STRING, n);
GB.Array.New(&tarray, GB_T_INTEGER, n);
GB.Array.New(&parray, GB_T_INTEGER, n);
pos = 0;
upos = 0;
i = 0;
for (p = 0; p < result.len; p++)
{
len = result.color[p].len;
if (result.color[p].state == RT_SPACE)
{
ulen = len;
}
else
{
ulen = 0;
for (l = 0; l < len; l++)
ulen += get_char_length(result.str[upos + ulen]);
str = GB.NewString(&result.str[upos], ulen);
*((char **)GB.Array.Get(garray, i)) = str;
*((int *)GB.Array.Get(tarray, i)) = convState(result.color[p].state);
*((int *)GB.Array.Get(parray, i)) = pos;
i++;
}
pos += len;
upos += ulen;
}
GB.Unref(&_analyze_symbol);
_analyze_symbol = garray;
GB.Ref(garray);
GB.Unref(&_analyze_type);
_analyze_type = tarray;
GB.Ref(tarray);
GB.Unref(&_analyze_pos);
_analyze_pos = parray;
GB.Ref(parray);
GB.FreeString(&_analyze_text);
_analyze_text = result.str;
}
BEGIN_METHOD_VOID(Highlight_exit)
GB.Unref(&_analyze_symbol);
GB.Unref(&_analyze_type);
GB.Unref(&_analyze_pos);
GB.FreeString(&_analyze_text);
GB.FreeString(&_purged_line);
END_METHOD
BEGIN_METHOD(Highlight_Purge, GB_STRING text; GB_BOOLEAN comment; GB_BOOLEAN string)
bool comment = VARGOPT(comment, FALSE);
bool string = VARGOPT(string, FALSE);
if (comment && string)
GB.ReturnNewString(STRING(text), LENGTH(text));
else
GB.ReturnString(purge(STRING(text), LENGTH(text), comment, string));
END_METHOD
BEGIN_METHOD(Highlight_Analyze, GB_STRING text; GB_BOOLEAN rewrite; GB_INTEGER state)
analyze(STRING(text), LENGTH(text), VARGOPT(rewrite, FALSE), VARGOPT(state, HIGHLIGHT_NORMAL));
GB.ReturnObject(_analyze_symbol);
END_METHOD
BEGIN_PROPERTY(Highlight_Symbols)
GB.ReturnObject(_analyze_symbol);
END_PROPERTY
BEGIN_PROPERTY(Highlight_Types)
GB.ReturnObject(_analyze_type);
END_PROPERTY
BEGIN_PROPERTY(Highlight_Positions)
GB.ReturnObject(_analyze_pos);
END_PROPERTY
BEGIN_PROPERTY(Highlight_TextAfter)
GB.ReturnString(_analyze_text);
END_PROPERTY
GB_DESC CHighlightDesc[] =
{
GB_DECLARE("Highlight", 0), GB_VIRTUAL_CLASS(),
GB_CONSTANT("Background", "i", HIGHLIGHT_BACKGROUND),
GB_CONSTANT("Normal", "i", HIGHLIGHT_NORMAL),
GB_CONSTANT("Keyword", "i", HIGHLIGHT_KEYWORD),
GB_CONSTANT("Function", "i", HIGHLIGHT_SUBR),
GB_CONSTANT("Operator", "i", HIGHLIGHT_OPERATOR),
GB_CONSTANT("Symbol", "i", HIGHLIGHT_SYMBOL),
GB_CONSTANT("Number", "i", HIGHLIGHT_NUMBER),
GB_CONSTANT("String", "i", HIGHLIGHT_STRING),
GB_CONSTANT("Comment", "i", HIGHLIGHT_COMMENT),
GB_CONSTANT("Breakpoint", "i", HIGHLIGHT_BREAKPOINT),
GB_CONSTANT("Current", "i", HIGHLIGHT_CURRENT),
GB_CONSTANT("DataType", "i", HIGHLIGHT_DATATYPE),
GB_CONSTANT("Selection", "i", HIGHLIGHT_SELECTION),
GB_CONSTANT("Highlight", "i", HIGHLIGHT_HIGHLIGHT),
GB_CONSTANT("CurrentLine", "i", HIGHLIGHT_LINE),
GB_CONSTANT("Error", "i", HIGHLIGHT_ERROR),
GB_CONSTANT("Help", "i", HIGHLIGHT_HELP),
GB_CONSTANT("Preprocessor", "i", HIGHLIGHT_PREPROCESSOR),
GB_CONSTANT("Escape", "i", HIGHLIGHT_ESCAPE),
GB_CONSTANT("Label", "i", HIGHLIGHT_LABEL),
GB_CONSTANT("Constant", "i", HIGHLIGHT_CONSTANT),
GB_CONSTANT("Alternate", "i", HIGHLIGHT_ALTERNATE),
GB_CONSTANT("Added", "i", HIGHLIGHT_ADDED),
GB_CONSTANT("Removed", "i", HIGHLIGHT_REMOVED),
GB_CONSTANT("Custom", "i", HIGHLIGHT_NUM_COLOR),
GB_STATIC_METHOD("_exit", NULL, Highlight_exit, NULL),
GB_STATIC_METHOD("Analyze", "String[]", Highlight_Analyze, "(Code)s[(Rewrite)b(State)i]"),
GB_STATIC_PROPERTY_READ("Symbols", "String[]", Highlight_Symbols),
GB_STATIC_PROPERTY_READ("Types", "Integer[]", Highlight_Types),
GB_STATIC_PROPERTY_READ("Positions", "Integer[]", Highlight_Positions),
GB_STATIC_PROPERTY_READ("TextAfter", "s", Highlight_TextAfter),
GB_STATIC_METHOD("Purge", "s", Highlight_Purge, "(Code)s[(Comment)b(String)b]"),
GB_END_DECLARE
};