improve c-mode, add mode_flags to handle language mode flavors

* add mode_flags and mode_name in EditState
* pass mode_flags to ColorizeFuncs
* define several CLANG mode flavors for C, C++, Javascript, Java, etc.
* add flavor specific keyword lists for c-mode
* add regex support in c-mode for Javascript flavor
This commit is contained in:
Charlie Gordon 2014-03-24 10:58:09 +00:00
commit b2c2c9374e
14 changed files with 201 additions and 82 deletions

View file

@ -103,8 +103,8 @@ static void build_bufed_list(EditState *s)
mode_name = "none";
for (e = qs->first_window; e != NULL; e = e->next_window) {
if (e->b == b1) {
if (e->mode) {
mode_name = e->mode->name;
if (e->mode_name) {
mode_name = e->mode_name;
break;
}
}

150
clang.c
View file

@ -21,41 +21,51 @@
#include "qe.h"
#if 0
static const char cc_keywords[] =
static const char cc_keywords[] = {
"asm|catch|class|delete|friend|inline|new|operator|"
"private|protected|public|template|try|this|virtual|throw|";
"private|protected|public|template|try|this|virtual|throw|"
};
static const char java_keywords[] =
"abstract|boolean|byte|catch|class|extends|false|final|"
"finally|function|implements|import|in|instanceof|"
"interface|native|new|null|package|private|protected|"
"public|super|synchronized|this|throw|throws|transient|"
"true|try|var|with|";
#endif
static const char js_keywords[] = {
"break|continue|delete|else|for|function|if|in|new|return|"
"this|typeof|var|void|while|with|case|catch|class|const|"
"debugger|default|do|enum|export|extends|finally|import|super|"
"switch|throw|try|undefined|null|true|false|"
};
static const char *c_mode_keywords =
static const char java_keywords[] = {
"abstract|boolean|break|byte|case|catch|class|const|continue|"
"default|do|alse|extends|false|final|finally|for|function|"
"if|implements|import|in|instanceof|interface|native|new|null|"
"package|private|protected|public|return|"
"static|super|switch|synchronized|"
"this|throw|throws|transient|true|try|var|while|with|"
};
static const char c_keywords[] = {
"auto|break|case|const|continue|default|do|else|enum|extern|for|goto|"
"if|inline|register|restrict|return|sizeof|static|struct|switch|"
"typedef|union|volatile|while|";
"typedef|union|volatile|while|"
};
/* NOTE: 'var' is added for javascript */
static const char *c_mode_types =
static const char c_mode_types[] = {
"char|double|float|int|long|unsigned|short|signed|void|var|"
"_Bool|_Complex|_Imaginary|";
"_Bool|_Complex|_Imaginary|"
};
static const char c_mode_extensions[] =
static const char c_mode_extensions[] = {
"c|h|C|H|" /* C language */
"y|l|lex|" /* yacc, lex */
"cc|hh|cpp|hpp|cxx|hxx|CPP|CC|c++|" /* C++ */
"m|" /* Objective-C */
"e|qe|cs|idl|"
"e|qe|cs|idl|st|"
"jav|java|js|json|" /* Java, Javascript, JSon */
"ec|ecp|" /* Informix embedded C */
"pgc|" /* Postgres embedded C */
"pcc|" /* Oracle C++ */
"cal" /* GNU Calc */
;
};
/* grab a C identifier from a uchar buf, stripping color.
* return char count.
@ -86,19 +96,23 @@ enum {
C_STRING = 4, /* double quoted string spanning multiple lines */
C_STRING_Q = 8, /* single quoted string spanning multiple lines */
C_PREPROCESS = 16, /* preprocessor directive with \ at EOL */
C_REGEX = 32, /* regex with \ at EOL */
};
void c_colorize_line(unsigned int *buf, int len,
void c_colorize_line(unsigned int *str, int n, int mode_flags,
int *colorize_state_ptr, __unused__ int state_only)
{
int c, state, style, style1, type_decl, klen, delim;
int i = 0, j = i, indent, c, state, style, style1, type_decl, klen, delim;
unsigned int *p, *p_start, *p_end, *p1, *p2;
char kbuf[32];
for (indent = 0; qe_isspace(str[indent]); indent++)
continue;
state = *colorize_state_ptr;
p = buf;
p = str;
p_start = p;
p_end = p + len;
p_end = p + n;
type_decl = 0;
if (p >= p_end)
@ -119,6 +133,8 @@ void c_colorize_line(unsigned int *buf, int len,
goto parse_string;
if (state & C_STRING_Q)
goto parse_string_q;
if (state & C_REGEX)
goto parse_regex;
}
while (p < p_end) {
@ -152,6 +168,44 @@ void c_colorize_line(unsigned int *buf, int len,
set_color(p_start, p, QE_STYLE_COMMENT);
goto the_end;
}
i = p - str - 1;
if ((mode_flags & CLANG_REGEX)
&& (i == indent
|| (str[i + 1] != ' ' && str[i + 1] != '='
&& !qe_isalnum(str[i - 1] & CHAR_MASK)
&& str[i - 1] != ')'))) {
/* XXX: should use mode context to tell regex from divide */
/* parse regex */
j = i + 1;
state = C_REGEX;
parse_regex:
while (j < n) {
/* XXX: should ignore / inside char classes */
c = str[j++];
if (c == '\\') {
if (j < n) {
j += 1;
}
} else
if (c == '#' && str[j] == '{') {
/* should parse full syntax */
while (j < n && str[j++] != '}')
continue;
} else
if (c == '/') {
while (qe_findchar("ensuimox", str[j])) {
j++;
}
state = 0;
break;
}
}
#define QE_STYLE_REGEX QE_STYLE_STRING_Q
SET_COLOR(str, i, j, QE_STYLE_REGEX);
i = j;
p = str + i;
continue;
}
break;
case '#': /* preprocessor */
state = C_PREPROCESS;
@ -231,7 +285,11 @@ void c_colorize_line(unsigned int *buf, int len,
} while (qe_isalnum_(c));
kbuf[klen] = '\0';
if (strfind(c_mode_keywords, kbuf)) {
if (((mode_flags & (CLANG_C|CLANG_CPP|CLANG_OBJC)) && strfind(c_keywords, kbuf))
|| ((mode_flags & CLANG_CPP) && strfind(cc_keywords, kbuf))
|| ((mode_flags & CLANG_JS) && strfind(js_keywords, kbuf))
|| ((mode_flags & CLANG_JAVA) && strfind(java_keywords, kbuf))
) {
set_color(p_start, p, QE_STYLE_KEYWORD);
continue;
}
@ -254,18 +312,18 @@ void c_colorize_line(unsigned int *buf, int len,
continue;
}
if (*p == '(') {
if (*p == '(' || (p[0] == ' ' && p[1] == '(')) {
/* function call */
/* XXX: different styles for call and definition */
set_color(p_start, p, QE_STYLE_FUNCTION);
continue;
}
/* assume typedef if starting at first column */
if (p_start == buf)
if (p_start == str)
type_decl = 1;
if (type_decl) {
if (p_start == buf) {
if (p_start == str) {
/* assume type if first column */
set_color(p_start, p, QE_STYLE_TYPE);
} else {
@ -280,7 +338,7 @@ void c_colorize_line(unsigned int *buf, int len,
}
the_end:
/* strip state if not overflowing from a comment */
if (!(state & C_COMMENT) && p > buf && ((p[-1] & CHAR_MASK) != '\\'))
if (!(state & C_COMMENT) && p > str && ((p[-1] & CHAR_MASK) != '\\'))
state &= ~(C_COMMENT1 | C_PREPROCESS);
*colorize_state_ptr = state;
}
@ -793,6 +851,45 @@ static int c_mode_probe(ModeDef *mode, ModeProbeData *p)
return 1;
}
static int c_mode_init(EditState *s, ModeSavedData *saved_data)
{
text_mode.mode_init(s, saved_data);
/* Select C like flavor */
if (match_extension(s->b->filename, "c|h|C|H")) {
s->mode_flags = CLANG_C;
} else
if (match_extension(s->b->filename, "cc|hh|cpp|hpp|cxx|hxx|CPP|CC|c++")) {
s->mode_name = "CPP";
s->mode_flags = CLANG_CPP;
} else
if (match_extension(s->b->filename, "m")) {
s->mode_name = "ObjC";
s->mode_flags = CLANG_OBJC;
} else
if (match_extension(s->b->filename, "js|json")) {
s->mode_name = "Javascript";
s->mode_flags = CLANG_JS | CLANG_REGEX;
} else
if (match_extension(s->b->filename, "st")) {
s->mode_name = "Syntax";
s->mode_flags = CLANG_C | CLANG_REGEX;
} else
if (match_extension(s->b->filename, "jav|java")) {
s->mode_name = "Java";
s->mode_flags = CLANG_JAVA;
} else
if (match_extension(s->b->filename, "l|lex")) {
s->mode_name = "Lex";
s->mode_flags = CLANG_C | CLANG_LEX;
} else
if (match_extension(s->b->filename, "y")) {
s->mode_name = "Yacc";
s->mode_flags = CLANG_C | CLANG_YACC;
}
return 0;
}
/* C mode specific commands */
static CmdDef c_commands[] = {
CMD2( KEY_CTRL('i'), KEY_NONE,
@ -822,6 +919,7 @@ static int c_init(void)
c_mode.name = "C";
c_mode.extensions = c_mode_extensions;
c_mode.mode_probe = c_mode_probe;
c_mode.mode_init = c_mode_init;
c_mode.colorize_func = c_colorize_line;
c_mode.indent_func = c_indent_line;

View file

@ -79,8 +79,8 @@ enum {
ASM_IDENTIFIER = QE_STYLE_VARIABLE,
};
static void asm_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void asm_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j, w;
int wn = 0; /* word number on line */
@ -246,8 +246,8 @@ enum {
BASIC_IDENTIFIER = QE_STYLE_VARIABLE,
};
static void basic_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void basic_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j;
@ -367,8 +367,8 @@ enum {
PAS_FUNCTION = QE_STYLE_FUNCTION,
};
static void pascal_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void pascal_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i, k;
int colstate = *statep;
@ -545,8 +545,8 @@ enum {
INI_PREPROCESS = QE_STYLE_PREPROCESS,
};
static void ini_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void ini_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j;
int bol = 1;
@ -694,8 +694,8 @@ enum {
#define ispssep(c) (qe_findchar(" \t\r\n,()<>[]{}/", c))
#define wrap 0
static void ps_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void ps_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j;
int colstate = *statep;
@ -783,6 +783,9 @@ static int ps_mode_probe(ModeDef *mode, ModeProbeData *p)
if (match_extension(p->filename, mode->extensions))
return 80;
if (*p->buf == '%' && qe_stristr((const char *)p->buf, "script"))
return 40;
return 1;
}
@ -819,8 +822,8 @@ enum {
SQL_PREPROCESS = QE_STYLE_PREPROCESS,
};
static void sql_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void sql_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i;
int state = *statep;
@ -963,8 +966,8 @@ static int lua_long_bracket(unsigned int *str, int *level)
}
}
void lua_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
void lua_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i, c, sep = 0, level = 0, level1, klen, style;
int state = *statep;
@ -1152,8 +1155,8 @@ static inline int haskell_is_symbol(int c)
return qe_findchar("!#$%&+./<=>?@\\^|-~:", c);
}
void haskell_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
void haskell_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i, c, sep = 0, level = 0, klen;
int state = *statep;
@ -1386,8 +1389,8 @@ enum {
PYTHON_FUNCTION = QE_STYLE_FUNCTION,
};
void python_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
void python_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i, c, sep = 0, klen;
int state = *statep;
@ -1672,8 +1675,8 @@ static int ruby_get_name(char *buf, int size, unsigned int *str)
return j - i;
}
void ruby_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
void ruby_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j = i, c, indent, sig;
static int sep, sep0, level; /* XXX: ugly patch */

View file

@ -66,7 +66,7 @@ enum {
HTML_SCRIPT = 0x80, /* <SCRIPT> [...] </SCRIPT> */
};
void htmlsrc_colorize_line(unsigned int *buf, int len,
void htmlsrc_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only)
{
int c, state, js_state, l;
@ -107,7 +107,8 @@ void htmlsrc_colorize_line(unsigned int *buf, int len,
c = *p; /* save char to set '\0' delimiter */
*p = '\0';
/* XXX: should have javascript specific colorize_func */
c_colorize_line(p_start, p - p_start, &js_state, state_only);
c_colorize_line(p_start, p - p_start, CLANG_JS | CLANG_REGEX,
&js_state, state_only);
*p = c;
state = js_state | HTML_SCRIPT;
if (p < p_end) {

View file

@ -26,6 +26,7 @@
* than one line (eg, multi-line functions and strings)
*/
static void latex_colorize_line(unsigned int *buf, __unused__ int len,
__unused__ int mode_flags,
int *colorize_state_ptr,
__unused__ int state_only)
{

4
lisp.c
View file

@ -31,8 +31,8 @@
#define LISP_COMMENT QE_STYLE_COMMENT
#define LISP_STRING QE_STYLE_STRING
static void lisp_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void lisp_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int colstate = *statep;
int i = 0, j = 0;

View file

@ -30,8 +30,8 @@
#define MAKEFILE_VARIABLE QE_STYLE_VARIABLE
#define MAKEFILE_MACRO QE_STYLE_TYPE
static void makefile_colorize_line(unsigned int *str, int n, int *statep,
int state_only)
static void makefile_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, int state_only)
{
int i, j, level;

View file

@ -102,8 +102,8 @@ static int mkd_scan_chunk(const unsigned int *str,
return 0;
}
static void mkd_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void mkd_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int colstate = *statep;
int level, indent, i = 0, j = 0, base_style = 0;
@ -117,7 +117,7 @@ static void mkd_colorize_line(unsigned int *str, int n, int *statep,
|| (str[i] == '<' && str[i + 1] != '/')) {
/* block level HTML markup */
colstate &= ~IN_HTML_BLOCK;
htmlsrc_colorize_line(str, n, &colstate, state_only);
htmlsrc_colorize_line(str, n, 0, &colstate, state_only);
colstate |= IN_HTML_BLOCK;
if ((str[i] & CHAR_MASK) == '<' && (str[i + 1] & CHAR_MASK) == '/')
colstate = 0;
@ -137,19 +137,19 @@ static void mkd_colorize_line(unsigned int *str, int n, int *statep,
colstate &= ~(IN_BLOCK | IN_LANG);
switch (lang) {
case IN_C:
c_colorize_line(str, n, &colstate, state_only);
c_colorize_line(str, n, CLANG_C, &colstate, state_only);
break;
case IN_PYTHON:
python_colorize_line(str, n, &colstate, state_only);
python_colorize_line(str, n, 0, &colstate, state_only);
break;
case IN_RUBY:
ruby_colorize_line(str, n, &colstate, state_only);
ruby_colorize_line(str, n, 0, &colstate, state_only);
break;
case IN_HASKELL:
haskell_colorize_line(str, n, &colstate, state_only);
haskell_colorize_line(str, n, 0, &colstate, state_only);
break;
case IN_LUA:
lua_colorize_line(str, n, &colstate, state_only);
lua_colorize_line(str, n, 0, &colstate, state_only);
break;
default:
SET_COLOR(str, i, n, QE_STYLE_MKD_CODE);

View file

@ -84,8 +84,8 @@ static int org_scan_chunk(const unsigned int *str,
return 0;
}
static void org_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void org_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int colstate = *statep;
int i = 0, j = 0, kw, base_style = 0, has_space;
@ -98,7 +98,7 @@ static void org_colorize_line(unsigned int *str, int n, int *statep,
} else {
if (colstate & IN_LISP) {
colstate &= ~(IN_LISP | IN_BLOCK);
lisp_mode.colorize_func(str, n, &colstate, state_only);
lisp_mode.colorize_func(str, n, 0, &colstate, state_only);
colstate |= IN_LISP | IN_BLOCK;
}
*statep = colstate;

4
perl.c
View file

@ -100,8 +100,8 @@ static int perl_string(const unsigned int *str, unsigned int delim,
return j;
}
static void perl_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void perl_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, c, c1, c2, j = i, s1, s2, delim = 0;
int colstate = *statep;

9
qe.c
View file

@ -1805,6 +1805,8 @@ static void edit_set_mode_full(EditState *s, ModeDef *m,
m = &text_mode;
}
s->mode = m;
s->mode_name = m->name;
s->mode_flags = 0;
/* init mode */
m->mode_init(s, saved_data);
@ -2183,7 +2185,7 @@ void basic_mode_line(EditState *s, buf_t *out, int c1)
buf_printf(out, "%c%c:%c%c %-20s (%s",
c1, state, s->b->flags & BF_READONLY ? '%' : mod,
mod, s->b->name, s->mode->name);
mod, s->b->name, s->mode_name);
if (!s->insert)
buf_printf(out, " Ovwrt");
if (s->interactive)
@ -3293,7 +3295,8 @@ int generic_get_colorized_line(EditState *s, unsigned int *buf, int buf_size,
for (l = s->colorize_nb_valid_lines; l <= line_num; l++) {
len = eb_get_line(s->b, buf, buf_size, &offset);
bom = (len > 0 && buf[0] == 0xFEFF);
s->colorize_func(buf + bom, len - bom, &colorize_state, 1);
s->colorize_func(buf + bom, len - bom, s->mode_flags,
&colorize_state, 1);
s->colorize_states[l] = colorize_state;
}
}
@ -3302,7 +3305,7 @@ int generic_get_colorized_line(EditState *s, unsigned int *buf, int buf_size,
colorize_state = s->colorize_states[line_num];
len = eb_get_line(s->b, buf, buf_size, offsetp);
bom = (len > 0 && buf[0] == 0xFEFF);
s->colorize_func(buf + bom, len - bom, &colorize_state, 0);
s->colorize_func(buf + bom, len - bom, s->mode_flags, &colorize_state, 0);
/* XXX: if state is same as previous, minimize invalid region? */
s->colorize_states[line_num + 1] = colorize_state;

25
qe.h
View file

@ -1045,7 +1045,7 @@ typedef int (*GetColorizedLineFunc)(EditState *s,
/* colorize a line: this function modifies buf to set the char
* styles. 'buf' is guaranted to have one more '\0' char after its len.
*/
typedef void (*ColorizeFunc)(unsigned int *buf, int len,
typedef void (*ColorizeFunc)(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
/* contains all the information necessary to uniquely identify a line,
@ -1114,6 +1114,8 @@ struct EditState {
/* maximum valid offset, INT_MAX if not modified. Needed to invalide
'colorize_states' */
int colorize_max_valid_offset;
int mode_flags; /* local mode flags for flavors */
const char *mode_name; /* name for mode flavor */
int busy; /* true if editing cannot be done if the window
(e.g. the parser HTML is parsing the buffer to
@ -1932,7 +1934,16 @@ void do_dired(EditState *s);
/* c_mode.c */
void c_colorize_line(unsigned int *buf, int len,
#define CLANG_C 0x01
#define CLANG_CPP 0x02
#define CLANG_OBJC 0x04
#define CLANG_JS 0x08
#define CLANG_JAVA 0x10
#define CLANG_LEX 0x20
#define CLANG_YACC 0x40
#define CLANG_REGEX 0x80
void c_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
/* xml.c */
@ -1941,7 +1952,7 @@ extern ModeDef xml_mode;
/* htmlsrc.c */
void htmlsrc_colorize_line(unsigned int *buf, int len,
void htmlsrc_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
/* html.c */
@ -1954,13 +1965,13 @@ int gxml_mode_init(EditState *s,
/* extra-modes.c */
void lua_colorize_line(unsigned int *buf, int len,
void lua_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
void haskell_colorize_line(unsigned int *buf, int len,
void haskell_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
void python_colorize_line(unsigned int *buf, int len,
void python_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
void ruby_colorize_line(unsigned int *buf, int len,
void ruby_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only);
/* image.c */

View file

@ -42,8 +42,8 @@ static int script_var(const unsigned int *str, int j, int n)
return j;
}
static void script_colorize_line(unsigned int *str, int n, int *statep,
__unused__ int state_only)
static void script_colorize_line(unsigned int *str, int n, int mode_flags,
int *statep, __unused__ int state_only)
{
int i = 0, j, style;

8
xml.c
View file

@ -30,7 +30,7 @@ enum {
XML_SCRIPT = 0x80, /* special mode for inside a script, ored with c mode */
};
static void xml_colorize_line(unsigned int *buf, int len,
static void xml_colorize_line(unsigned int *buf, int len, int mode_flags,
int *colorize_state_ptr, int state_only)
{
int c, state;
@ -112,7 +112,8 @@ static void xml_colorize_line(unsigned int *buf, int len,
if (*p == '\0') {
state &= ~XML_SCRIPT;
/* XXX: should have javascript specific colorize_func */
c_colorize_line(p_start, p - p_start, &state, state_only);
c_colorize_line(p_start, p - p_start,
CLANG_C | CLANG_REGEX, &state, state_only);
state |= XML_SCRIPT;
break;
} else
@ -125,7 +126,8 @@ static void xml_colorize_line(unsigned int *buf, int len,
c = *p;
*p = '\0';
/* XXX: should have javascript specific colorize_func */
c_colorize_line(p_start, p - p_start, &state, state_only);
c_colorize_line(p_start, p - p_start,
CLANG_C | CLANG_REGEX, &state, state_only);
*p = c;
state |= XML_SCRIPT;
set_color(p, p1, QE_STYLE_TAG);