enventor/src/lib/syntax_color.c

1015 lines
27 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Enventor.h>
#include "enventor_private.h"
#define MAX_COL_NUM 6
typedef struct color_tuple
{
Eina_Stringshare *key;
Eina_Stringshare *col;
} color_tuple;
typedef struct color
{
char *val;
Eina_List *keys;
} color;
typedef struct syntax_color_group
{
char *string;
char *comment;
char *macro;
char *count;
color colors[MAX_COL_NUM];
} syntax_color_group;
typedef struct syntax_color_source
{
Eina_Hash *color_hash;
Eina_Stringshare *col_string;
Eina_Stringshare *col_comment;
Eina_Stringshare *col_macro;
Eina_Stringshare *cols[MAX_COL_NUM];
int color_cnt;
} syntax_color_source;
struct syntax_color_s
{
Eina_Strbuf *strbuf;
Eina_Strbuf *cachebuf;
Eina_List *macros;
syntax_color_source *col_src;
};
typedef struct color_hash_foreach_data
{
Eina_Stringshare *cur_col;
Eina_Stringshare *new_col;
} color_hash_foreach_data;
static Eet_Data_Descriptor *edd_scg = NULL;
static Eet_Data_Descriptor *edd_color = NULL;
static syntax_color_group *scg = NULL;
//We could share this color source through editor instances.
static syntax_color_source g_color_src;
static int init_count = 0;
/*****************************************************************************/
/* Internal method implementation */
/*****************************************************************************/
static void
hash_free_cb(void *data)
{
Eina_Inarray *inarray = data;
color_tuple *tuple;
EINA_INARRAY_FOREACH(inarray, tuple)
eina_stringshare_del(tuple->key);
eina_inarray_free(inarray);
}
static void
eddc_init(void)
{
Eet_Data_Descriptor_Class eddc;
eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc),
"syntax_color_group",
sizeof(syntax_color_group));
edd_scg = eet_data_descriptor_stream_new(&eddc);
eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc), "color",
sizeof(color));
edd_color = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_scg, syntax_color_group, "string",
string, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_scg, syntax_color_group, "comment",
comment, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_scg, syntax_color_group, "macro",
macro, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_scg, syntax_color_group, "count",
count, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(edd_color, color, "val", val, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_LIST_STRING(edd_color, color, "keys", keys);
EET_DATA_DESCRIPTOR_ADD_ARRAY(edd_scg, syntax_color_group, "colors",
colors, edd_color);
}
static void
eddc_term(void)
{
eet_data_descriptor_free(edd_scg);
eet_data_descriptor_free(edd_color);
}
static void
color_load()
{
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%s/color/edc.eet", elm_app_data_dir_get());
Eet_File *ef = eet_open(buf, EET_FILE_MODE_READ);
if (ef)
{
scg = eet_data_read(ef, edd_scg, "color");
if (!scg) EINA_LOG_ERR("Failed to read syntax color group.");
eet_close(ef);
}
else EINA_LOG_ERR("Failed to open color data file \"%s\"", buf);
}
static void
color_table_init(void)
{
color_tuple tuple;
int i;
Eina_List *l;
char *key;
char tmp[2];
Eina_Inarray *inarray;
if (!scg) return;
syntax_color_source *color_src = &g_color_src;
color_src->col_string = eina_stringshare_add(scg->string);
//free(scg->string);
color_src->col_comment = eina_stringshare_add(scg->comment);
//free(scg->comment);
color_src->col_macro = eina_stringshare_add(scg->macro);
//free(scg->macro);
color_src->color_cnt = atoi(scg->count);
//free(scg->count);
color_src->color_hash = eina_hash_string_small_new(hash_free_cb);
for (i = 0; i < color_src->color_cnt; i++)
{
color_src->cols[i] = eina_stringshare_add(scg->colors[i].val);
//free(scg->colors[i].val);
EINA_LIST_FOREACH(scg->colors[i].keys, l, key)
{
tmp[0] = key[0];
tmp[1] = '\0';
inarray = eina_hash_find(color_src->color_hash, tmp);
if (!inarray)
{
inarray = eina_inarray_new(sizeof(color_tuple), 20);
eina_hash_add(color_src->color_hash, tmp, inarray);
}
tuple.col = color_src->cols[i];
tuple.key = eina_stringshare_add(key);
eina_inarray_push(inarray, &tuple);
}
eina_list_free(scg->colors[i].keys);
}
free(scg);
scg = NULL;
}
static void
macro_key_push(color_data *cd, char *str)
{
char *key = str;
syntax_color_source *col_src = cd->col_src;
//cutoff "()" from the macro name
char *cut = strchr(key, '(');
if (cut)
{
key = eina_strndup(str, cut - str);
if (!key) return;
}
char tmp[2];
tmp[0] = key[0];
tmp[1] = '\0';
Eina_Inarray *inarray = eina_hash_find(col_src->color_hash, tmp);
if (!inarray)
{
inarray = eina_inarray_new(sizeof(color_tuple), 20);
eina_hash_add(col_src->color_hash, tmp, inarray);
}
color_tuple tuple;
tuple.col = col_src->col_macro;
tuple.key = eina_stringshare_add(key);
eina_inarray_push(inarray, &tuple);
cd->macros = eina_list_append(cd->macros, eina_stringshare_add(tuple.key));
if (cut) free(key);
}
static Eina_Bool
color_markup_insert_internal(Eina_Strbuf *strbuf, const char **src, int length,
char **cur, char **prev, const char *cmp,
Eina_Stringshare *col)
{
char buf[128];
eina_strbuf_append_length(strbuf, *prev, *cur - *prev);
snprintf(buf, sizeof(buf), "<color=#%s>%s</color>", col, cmp);
eina_strbuf_append(strbuf, buf);
*cur += strlen(cmp);
if (*cur > (*src + length)) return EINA_FALSE;
*prev = *cur;
return EINA_TRUE;
}
static int
markup_skip(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev)
{
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
(*cur)++;
if (*cur > (*src + length)) return -1;
*prev = *cur;
*cur = strchr(*prev, '>');
if (*cur)
{
(*cur)++;
*prev = *cur;
return 1;
}
else
{
*prev = *cur;
return -1;
}
return 1;
}
static int
comment_apply(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev, const Eina_Stringshare *col,
Eina_Bool *inside_comment)
{
if (!(*inside_comment))
{
if ((*cur)[0] != '/') return 0;
if ((*cur) + 1 > ((*src) + length)) return -1;
if ((*cur)[1] != '*') return 0;
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
char buf[128];
snprintf(buf, sizeof(buf), "<color=#%s>/*", col);
eina_strbuf_append(strbuf, buf);
int cmp_size = 2; //strlen("/*");
*cur += cmp_size;
if (*cur > (*src + length))
{
*inside_comment = EINA_TRUE;
return -1;
}
*prev = *cur;
*cur = strstr(*prev, "*/");
if (*cur)
{
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
eina_strbuf_append(strbuf, "*/</color>");
*cur += cmp_size;
*prev = *cur;
return 0;
}
eina_strbuf_append(strbuf, *prev);
*prev = *cur;
*inside_comment = EINA_TRUE;
return -1;
}
else
{
if ((*cur)[0] != '*') return 0;
if ((*cur) + 1 > ((*src) + length)) return -1;
if ((*cur)[1] != '/') return 0;
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
eina_strbuf_append(strbuf, "*/</color>");
int cmp_size = 2; //strlen("*/");
*cur += cmp_size;
*inside_comment = EINA_FALSE;
if (*cur > (*src + length)) return -1;
*prev = *cur;
return 1;
}
return -1;
}
static int
comment2_apply(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev, const Eina_Stringshare *col,
Eina_Bool *inside_comment)
{
if (*inside_comment) return 0;
if ((*cur)[0] != '/') return 0;
if (((*cur) + 1) > ((*src) + length)) return -1;
if ((*cur)[1] != '/') return 0;
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
char buf[128];
snprintf(buf, sizeof(buf), "<color=#%s>//", col);
eina_strbuf_append(strbuf, buf);
int cmp_size = 2; //strlen("//");
*cur += cmp_size;
if (*cur > (*src + length))
{
eina_strbuf_append(strbuf, "</color>");
return -1;
}
*prev = *cur;
*cur = strstr(*prev, EOL);
if (*cur)
{
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
eina_strbuf_append(strbuf, "</color><br/>");
*cur += EOL_LEN;
*prev = *cur;
return 1;
}
eina_strbuf_append(strbuf, *prev);
*prev = *cur;
eina_strbuf_append(strbuf, "</color>");
return -1;
}
static int
string_apply(Eina_Strbuf *strbuf, char **cur, char **prev,
const Eina_Stringshare *col, Eina_Bool inside_string)
{
//escape string: " ~ "
Eina_Bool is_eol = EINA_FALSE;
if (inside_string && !strncmp(*cur, EOL, EOL_LEN)) is_eol = EINA_TRUE;
else if (strncmp(*cur, QUOT, QUOT_LEN)) return 0;
char buf[128];
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
// these conditions limit string range to end of line
// case 1: this condition checks end of line for string
if (is_eol)
{
snprintf(buf, sizeof(buf), "</color>");
eina_strbuf_append(strbuf, buf);
}
// case 2: this condition checks start and end for string
else
{
if (!inside_string)
snprintf(buf, sizeof(buf), "<color=#%s>%s", col, QUOT);
else
snprintf(buf, sizeof(buf), "%s</color>", QUOT);
eina_strbuf_append(strbuf, buf);
*cur += QUOT_LEN;
}
*prev = *cur;
return 1;
}
static int
macro_apply(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev, const Eina_Stringshare *col, color_data *cd)
{
if ((*cur)[0] != '#') return 0;
char *space = strchr(*cur, ' ');
const char *eol = strstr(*cur, EOL);
if (!eol) eol = (*src) + length;
if (!space) space = (char *) eol;
//Let's find the macro name
while ((*space == ' ') && (space != eol)) space++;
char *macro_begin = space;
char *macro_end = strchr(space, ' ');
//Excetional case 1
if (!macro_end) macro_end = (char *) eol;
//Exceptional case 2
else if (macro_end > eol) macro_end = (char *) eol;
//Let's check the macro function case
else
{
int macro_len = macro_end - macro_begin;
char *macro = alloca(macro_len);
strncpy(macro, macro_begin, macro_len);
//Check how many "(", ")" pairs are exists
int bracket_inside = 0;
while (macro_len > 0)
{
if (macro[macro_len - 1] == '(') bracket_inside++;
else if (macro[macro_len - 1] == ')') bracket_inside--;
macro_len--;
}
if (bracket_inside > 0)
{
while (bracket_inside > 0)
{
macro_end = strchr(macro_end, ')');
if (!macro_end) break;
bracket_inside--;
}
if (!macro_end) macro_end = (char *) eol;
else if (macro_end > eol) macro_end = (char *) eol;
else macro_end++;
}
}
//#define, #ifdef, #if, #...
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
char buf[128];
snprintf(buf, sizeof(buf), "<color=#%s>#", col);
eina_strbuf_append(strbuf, buf);
int cmp_size = 1; //strlen("#");
*cur += cmp_size;
*prev = *cur;
*cur = macro_end;
//push the macro to color table but only not numeric case.
if ((macro_end > macro_begin) &&
((macro_begin[0] < '0') || (macro_begin[0] > '9')))
{
char *macro = eina_strndup(macro_begin, (macro_end - macro_begin));
macro_key_push(cd, macro);
free(macro);
}
//Apply macro color to whole macro area continues to the "\".
while (macro_end < (*src + length))
{
char *slash = strstr(macro_end, "\\");
char *endeol = strstr(macro_end, EOL);
if ((!slash && endeol) ||
((slash && endeol) && (slash > endeol)))
{
macro_end = endeol;
break;
}
if (!slash || !endeol) break;
if (endeol < slash) break;
macro_end = endeol + 1;
}
*cur = macro_end;
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev));
eina_strbuf_append(strbuf, "</color>");
*prev = *cur;
return 1;
}
const char *
color_cancel(Ecore_Thread *thread, color_data *cd, const char *src,
int length, int from_pos, int to_pos, char **from, char **to)
{
if (!src || length < 1) return NULL;
Eina_Strbuf *strbuf = cd->strbuf;
eina_strbuf_reset(strbuf);
const char *str = NULL;
char *prev = (char *) src;
char *cur = (char *) src;
int line = 1;
Eina_Bool find_from, find_to;
//if the from_pos equals -1, we wanna full text area of syntax color
if (from_pos == -1)
{
find_from = EINA_FALSE;
find_to = EINA_FALSE;
}
else
{
find_from = EINA_TRUE;
find_to = EINA_TRUE;
}
while (cur && (cur <= (src + length)))
{
if (thread && ecore_thread_check(thread)) return NULL;
//Capture start line
if (find_from && (line == from_pos))
{
from_pos = eina_strbuf_length_get(strbuf);
find_from = EINA_FALSE;
}
if (*cur == '<')
{
//escape EOL: <br/>
if (!strncmp(cur, EOL, EOL_LEN))
{
//Capture end line
if (find_to && (line == to_pos))
{
to_pos = eina_strbuf_length_get(strbuf);
find_to = EINA_FALSE;
}
eina_strbuf_append_length(strbuf, prev,
(cur - prev + EOL_LEN));
cur += EOL_LEN;
prev = cur;
line++;
continue;
}
//escape TAB: <tab/>
if (!strncmp(cur, TAB, TAB_LEN))
{
cur += TAB_LEN;
continue;
}
//escape markups: <..> ~ </..>
if (markup_skip(strbuf, &src, length, &cur, &prev) == 1)
continue;
}
cur++;
}
//Capture end line
if (find_to && (line == to_pos))
{
to_pos = eina_strbuf_length_get(strbuf);
find_to = EINA_FALSE;
}
//Same with origin source.
if (prev == src)
str = src;
//Some color syntax is applied.
else
{
//append leftovers.
if (prev + 1 < cur) eina_strbuf_append(strbuf, prev);
str = eina_strbuf_string_get(strbuf);
}
//Exceptional Handling
if (find_from) from_pos = 0;
if (find_to) to_pos = eina_strbuf_length_get(strbuf);
if (from_pos != -1)
{
*from = ((char *) str) + from_pos;
*to = ((char *) str) + to_pos;
}
return str;
}
static void
macro_keys_free(color_data *cd)
{
Eina_Stringshare *macro;
Eina_Inarray *inarray;
color_tuple *tuple;
char key[2];
syntax_color_source *col_src = cd->col_src;
EINA_LIST_FREE(cd->macros, macro)
{
key[0] = macro[0];
key[1] = '\0';
inarray = eina_hash_find(col_src->color_hash, key);
if (inarray)
{
EINA_INARRAY_REVERSE_FOREACH(inarray, tuple)
{
if (strlen(macro) != strlen(tuple->key)) continue;
if (!strcmp(macro, tuple->key))
{
eina_inarray_pop(inarray);
break;
}
}
}
}
}
static int
color_markup_insert(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev, color_data *cd)
{
const char *SYMBOLS = " {}[];:.()!<>=&|/";
Eina_Bool symbol = EINA_FALSE;
if (strchr(SYMBOLS, (*cur)[0])) symbol = EINA_TRUE;
if (!symbol && (*cur > *src))
{
if (!strchr(SYMBOLS, *(*cur -1))) return 0;
}
syntax_color_source *col_src = cd->col_src;
char tmp[2];
tmp[0] = (*cur)[0];
tmp[1] = '\0';
Eina_Inarray *inarray = eina_hash_find(col_src->color_hash, tmp);
if (!inarray) return 0;
//Found tuple list. Search in detail.
color_tuple *tuple;
int len;
EINA_INARRAY_FOREACH(inarray, tuple)
{
len = strlen(tuple->key);
char *p = *cur + len;
if (!strncmp(*cur, tuple->key, len))
{
if (p <= (*src + length))
{
if (!symbol &&
/* Exceptional Case. For duplicated keywords, it
subdivides with '.' ' '. See the config.src */
(*(p - 1) != '.') &&
(*(p - 1) != ' '))
{
if (!strchr(SYMBOLS, *p)) return 0;
}
if (color_markup_insert_internal(strbuf, src, length, cur,
prev, tuple->key,
tuple->col))
return 1;
else return -1;
}
}
}
return 0;
}
/*****************************************************************************/
/* Externally accessible calls */
/*****************************************************************************/
color_data *
color_init(Eina_Strbuf *strbuf)
{
color_data *cd = calloc(1, sizeof(color_data));
if (!cd)
{
mem_fail_msg();
return NULL;
}
init_count++;
cd->strbuf = strbuf;
cd->cachebuf = eina_strbuf_new();
if (init_count == 1)
{
eddc_init();
color_load();
eddc_term();
color_table_init();
}
cd->col_src = &g_color_src;
/* TODO: Improve to share macro info through color instances. Might be this
could be global static instance and could be shared with locking
mechanism... */
cd->macros = NULL;
return cd;
}
void
color_term(color_data *cd)
{
Eina_Stringshare *macro;
EINA_LIST_FREE(cd->macros, macro) eina_stringshare_del(macro);
eina_strbuf_free(cd->cachebuf);
free(cd);
//release shared color source.
if ((--init_count) == 0)
{
syntax_color_source *col_src = &g_color_src;
eina_hash_free(col_src->color_hash);
eina_stringshare_del(col_src->col_string);
eina_stringshare_del(col_src->col_comment);
eina_stringshare_del(col_src->col_macro);
int i;
for(i = 0; i < col_src->color_cnt; i++)
eina_stringshare_del(col_src->cols[i]);
}
}
static Eina_Bool
color_hash_foreach_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *data, void *fdata)
{
Eina_Inarray *inarray = data;
color_hash_foreach_data *fd = fdata;
color_tuple *tuple;
EINA_INARRAY_FOREACH(inarray, tuple)
{
if (tuple->col == fd->cur_col)
tuple->col = fd->new_col;
}
return EINA_TRUE;
}
//FIXME: Need synchronization... ?
void
color_set(color_data *cd, Enventor_Syntax_Color_Type color_type,
const char *val)
{
Eina_Stringshare *col;
color_hash_foreach_data fd;
syntax_color_source *col_src = cd->col_src;
switch (color_type)
{
case ENVENTOR_SYNTAX_COLOR_STRING:
{
eina_stringshare_del(col_src->col_string);
col_src->col_string = eina_stringshare_add(val);
break;
}
case ENVENTOR_SYNTAX_COLOR_COMMENT:
{
eina_stringshare_del(col_src->col_comment);
col_src->col_comment = eina_stringshare_add(val);
break;
}
case ENVENTOR_SYNTAX_COLOR_MACRO:
{
eina_stringshare_del(col_src->col_macro);
col_src->col_macro = eina_stringshare_add(val);
break;
}
case ENVENTOR_SYNTAX_COLOR_SYMBOL:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[0];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[0]);
col_src->cols[0] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_MAIN_KEYWORD:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[1];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[1]);
col_src->cols[1] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_SUB_KEYWORD:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[2];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[2]);
col_src->cols[2] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_CONSTANT:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[3];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[3]);
col_src->cols[3] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_SCRIPT_FUNC:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[4];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[4]);
col_src->cols[4] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_SCRIPT_KEYWORD:
{
col = eina_stringshare_add(val);
fd.cur_col = col_src->cols[5];
fd.new_col = col;
eina_hash_foreach(col_src->color_hash, color_hash_foreach_cb, &fd);
eina_stringshare_del(col_src->cols[5]);
col_src->cols[5] = col;
break;
}
case ENVENTOR_SYNTAX_COLOR_LAST: //avoiding compiler warning
break;
}
}
const char *
color_value_get(Enventor_Syntax_Color_Type color_type)
{
syntax_color_source *col_src = &g_color_src;
if (!col_src) return NULL;
switch (color_type)
{
case ENVENTOR_SYNTAX_COLOR_STRING:
return (const char *) col_src->col_string;
case ENVENTOR_SYNTAX_COLOR_COMMENT:
return (const char *) col_src->col_comment;
case ENVENTOR_SYNTAX_COLOR_MACRO:
return (const char *) col_src->col_macro;
case ENVENTOR_SYNTAX_COLOR_SYMBOL:
return (const char *) col_src->cols[0];
case ENVENTOR_SYNTAX_COLOR_MAIN_KEYWORD:
return (const char *) col_src->cols[1];
case ENVENTOR_SYNTAX_COLOR_SUB_KEYWORD:
return (const char *) col_src->cols[2];
case ENVENTOR_SYNTAX_COLOR_CONSTANT:
return (const char *) col_src->cols[3];
case ENVENTOR_SYNTAX_COLOR_SCRIPT_FUNC:
return (const char *) col_src->cols[4];
case ENVENTOR_SYNTAX_COLOR_SCRIPT_KEYWORD:
return (const char *) col_src->cols[5];
default:
return NULL;
}
}
const char *
color_apply(Ecore_Thread *thread, color_data *cd, const char *src, int length,
char *from, char *to)
{
Eina_Bool inside_string = EINA_FALSE;
Eina_Bool inside_comment = EINA_FALSE;
if (!src || (length < 1)) return NULL;
syntax_color_source *col_src = cd->col_src;
Eina_Strbuf *strbuf = cd->cachebuf;
eina_strbuf_reset(strbuf);
const char *str = NULL;
char *prev = (char *) src;
char *cur = (char *) src;
int ret;
while (cur && (cur <= (src + length)))
{
if (thread && ecore_thread_check(thread)) return NULL;
//escape empty string
if (!from || (cur >= from))
{
if (cur[0] == ' ')
{
if (cur > prev)
eina_strbuf_append_length(strbuf, prev, (cur - prev) + 1);
else
eina_strbuf_append_char(strbuf, ' ');
++cur;
prev = cur;
continue;
}
}
//escape string: " ~ "
ret = string_apply(strbuf, &cur, &prev, col_src->col_string,
inside_string);
if (ret == 1)
{
inside_string = !inside_string;
continue;
}
if (inside_string || inside_comment)
{
cur++;
continue;
}
//handle comment: /* ~ */
ret = comment_apply(strbuf, &src, length, &cur, &prev,
col_src->col_comment, &inside_comment);
if (ret == 1) continue;
else if (ret == -1) goto finished;
//handle comment: //
if (!from || (cur >= from))
{
ret = comment2_apply(strbuf, &src, length, &cur, &prev,
col_src->col_comment, &inside_comment);
if (ret == 1) continue;
else if (ret == -1) goto finished;
}
if (*cur == '<')
{
//escape EOL: <br/>
if (!strncmp(cur, EOL, EOL_LEN))
{
cur += EOL_LEN;
continue;
}
//escape TAB: <tab/>
if (!strncmp(cur, TAB, TAB_LEN))
{
cur += TAB_LEN;
continue;
}
}
//handle comment: preprocessors, #
ret = macro_apply(strbuf, &src, length, &cur, &prev, col_src->col_macro,
cd);
if (ret == 1) continue;
//apply color markup
if (!from || (cur >= from))
{
ret = color_markup_insert(strbuf, &src, length, &cur, &prev, cd);
if (ret == 1) continue;
else if (ret == -1) goto finished;
}
cur++;
if (to && (cur > to)) goto finished;
}
//Same with origin source.
if (prev == src)
str = src;
//Some color syntax is applied.
else
{
finished:
//append leftovers.
if (prev < cur) eina_strbuf_append(strbuf, prev);
str = eina_strbuf_string_get(strbuf);
}
macro_keys_free(cd);
return str;
}