diff --git a/Makefile b/Makefile index 9715153..2b466dd 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,8 @@ OBJS+=charsetjis.o charsetmore.o endif ifdef CONFIG_ALL_MODES -OBJS+= unihex.o clang.o latex-mode.o xml.o bufed.o +OBJS+= unihex.o clang.o latex-mode.o xml.o bufed.o \ + makemode.o perl.o htmlsrc.o ifndef CONFIG_WIN32 OBJS+= shell.o dired.o endif @@ -189,13 +190,15 @@ libqhtml: force qe_g$(EXE): $(OBJS) $(DEP_LIBS) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -qe$(EXE): qe_g$(EXE) +qe$(EXE): qe_g$(EXE) Makefile rm -f $@ cp $< $@ $(STRIP) $@ @ls -l $@ + echo `size qe` `wc --bytes qe` qe $(OPTIONS) \ + | cut -d ' ' -f 7-10,13,15-40 >> STATS -ffplay$(EXE): qe$(EXE) +ffplay$(EXE): qe$(EXE) Makefile ln -sf $< $@ qe.o: qe.c qe.h qfribidi.h qeconfig.h @@ -216,13 +219,13 @@ fbfrender.o: fbfrender.c fbfrender.h libfbf.h html2png.o: html2png.c qe.h -%.o : %.c +%.o: %.c qe.h Makefile $(CC) $(DEFINES) $(CFLAGS) -o $@ -c $< clean: make -C libqhtml clean - rm -f *.o *.exe *~ TAGS gmon.out core *.exe.stackdump \ - qe qe_g qfribidi kmaptoqe ligtoqe html2png fbftoqe fbffonts.c \ + rm -f *~ *.o *.a *.exe *_g TAGS gmon.out core *.exe.stackdump \ + qe qfribidi kmaptoqe ligtoqe html2png fbftoqe fbffonts.c \ cptoqe jistoqe distclean: clean @@ -391,7 +394,7 @@ OBJS=util.o cutils.o \ libfbf.o fbfrender.o cfb.o fbffonts.o html2png$(EXE): html2png.o $(OBJS) libqhtml/libqhtml.a - $(HOST_CC) $(LDFLAGS) -o $@ html2png.o $(OBJS) \ + $(CC) $(LDFLAGS) -o $@ html2png.o $(OBJS) \ -L./libqhtml -lqhtml $(HTMLTOPPM_LIBS) # autotest target diff --git a/clang.c b/clang.c index e0dc3a9..92ab9e1 100644 --- a/clang.c +++ b/clang.c @@ -20,18 +20,34 @@ #include "qe.h" -static const char c_keywords[] = - "|auto|break|case|const|continue|default|do|else|enum|extern|for|goto|" +#if 0 +static const char cc_keywords[] = + "asm|catch|class|delete|friend|inline|new|operator|" + "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 *c_mode_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|"; /* NOTE: 'var' is added for javascript */ -static const char c_types[] = - "|char|double|float|int|long|unsigned|short|signed|void|var|" - "_Bool|_Complex|_Imaginary"; +static const char *c_mode_types = + "char|double|float|int|long|unsigned|short|signed|void|var|" + "_Bool|_Complex|_Imaginary|"; + +static const char *c_mode_extensions = + "c|h|y|e|cc|cs|cpp|cxx|hpp|hxx|jav|java|js|qe|"; #if 0 -static int get_c_keyword(char *buf, int buf_size, unsigned int *p) +static int get_c_identifier(char *buf, int buf_size, unsigned int *p) { unsigned int c; char *q; @@ -51,26 +67,31 @@ static int get_c_keyword(char *buf, int buf_size, unsigned int *p) } #endif -/* colorization states */ +/* c-mode colorization states */ enum { - C_COMMENT = 1, - C_COMMENT1 = 2, - C_STRING = 4, - C_STRING_Q = 8, - C_PREPROCESS = 16, + C_COMMENT = 1, /* multiline comment pending */ + C_COMMENT1 = 2, /* single line comment with \ at EOL */ + 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 */ }; void c_colorize_line(unsigned int *buf, int len, int *colorize_state_ptr, __unused__ int state_only) { int c, state, style, klen, type_decl; - unsigned int *p, *p_start, *p1, *p2; + unsigned int *p, *p_start, *p_end, *p1, *p2; char kbuf[32]; state = *colorize_state_ptr; p = buf; p_start = p; + p_end = p + len; type_decl = 0; + + if (p >= p_end) + goto the_end; + c = 0; /* turn off stupid egcs-2.91.66 warning */ style = 0; @@ -88,7 +109,7 @@ void c_colorize_line(unsigned int *buf, int len, goto parse_string_q; } - for (;;) { + while (p < p_end) { p_start = p; c = *p++; @@ -97,20 +118,12 @@ void c_colorize_line(unsigned int *buf, int len, p--; goto the_end; case '/': - if (*p == '/') { - /* line comment */ - parse_comment1: - state |= C_COMMENT1; - p = buf + len; - set_color(p_start, p, QE_STYLE_COMMENT); - goto the_end; - } else if (*p == '*') { /* normal comment */ p++; parse_comment: state |= C_COMMENT; - while (*p != '\n') { + while (p < p_end) { if (p[0] == '*' && p[1] == '/') { p += 2; state &= ~C_COMMENT; @@ -121,6 +134,14 @@ void c_colorize_line(unsigned int *buf, int len, } set_color(p_start, p, QE_STYLE_COMMENT); continue; + } else + if (*p == '/') { + /* line comment */ + parse_comment1: + state |= C_COMMENT1; + p = p_end; + set_color(p_start, p, QE_STYLE_COMMENT); + goto the_end; } break; case '#': /* preprocessor */ @@ -143,10 +164,10 @@ void c_colorize_line(unsigned int *buf, int len, case '\'': /* character constant */ parse_string_q: state |= C_STRING_Q; - for (; *p != '\n'; p++) { + for (; p < p_end; p++) { if (*p == '\\') { p++; - if (*p == '\n') + if (p >= p_end) break; } else if (*p == '\'') { @@ -162,10 +183,10 @@ void c_colorize_line(unsigned int *buf, int len, case '\"': /* strings literal */ parse_string: state |= C_STRING; - for (; *p != '\n'; p++) { + for (; p < p_end; p++) { if (*p == '\\') { p++; - if (*p == '\n') + if (p >= p_end) break; } else if (*p == '\"') { @@ -209,18 +230,19 @@ void c_colorize_line(unsigned int *buf, int len, p++; c = *p; } while (qe_isalnum(c) || c == '_'); - kbuf[klen] = '\0'; + p1 = p; while (qe_isblank(*p1)) p1++; p2 = p1; while (*p2 == '*' || qe_isblank(*p2)) p2++; - if (strfind(c_keywords, kbuf, 0)) { + + if (strfind(c_mode_keywords, kbuf, 0)) { set_color(p_start, p, QE_STYLE_KEYWORD); } else - if (strfind(c_types, kbuf, 0) + if (strfind(c_mode_types, kbuf, 0) || (klen > 2 && kbuf[klen - 2] == '_' && kbuf[klen - 1] == 't')) { /* c type */ /* if not cast, assume type declaration */ @@ -515,7 +537,7 @@ static void do_c_indent(EditState *s) /* the number of needed spaces is in 'pos' */ - /* CG: should not modify buffer is indentation in correct */ + /* CG: should not modify buffer if indentation in correct */ /* suppress leading spaces */ offset1 = offset; @@ -561,6 +583,7 @@ static void do_c_indent_region(EditState *s) } /* move point to end of region, and mark to begin of first row */ s->offset = s->b->mark; + /* XXX: begin may have moved? */ s->b->mark = begin; } @@ -570,30 +593,6 @@ static void do_c_electric(EditState *s, int key) do_c_indent(s); } -static int c_mode_probe(ModeProbeData *p) -{ - const char *r; - - /* currently, only use the file extension */ - r = extension(p->filename); - if (*r) { - if (strfind("|c|e|h|js|cs|jav|java|cxx|cpp|", r + 1, 1)) - return 100; - } - return 0; -} - -static int c_mode_init(EditState *s, ModeSavedData *saved_data) -{ - int ret; - - ret = text_mode_init(s, saved_data); - if (ret) - return ret; - set_colorize_func(s, c_colorize_line); - return ret; -} - /* forward / backward preprocessor */ static void do_c_forward_preprocessor(EditState *s, int dir) { @@ -602,6 +601,7 @@ static void do_c_forward_preprocessor(EditState *s, int dir) /* forward / backward block */ #define MAX_LEVEL 20 +/* CG: move this to generic command */ static void do_c_forward_block(EditState *s, int dir) { unsigned int buf[MAX_BUF_SIZE]; @@ -721,6 +721,7 @@ the_end: s->offset = offset; } +/* CG: move this to generic command */ static void do_c_kill_block(EditState *s, int dir) { int start = s->offset; @@ -732,7 +733,27 @@ static void do_c_kill_block(EditState *s, int dir) do_kill(s, start, s->offset, dir); } -/* specific C commands */ +static int c_mode_probe(ModeProbeData *p) +{ + /* currently, only use the file extension */ + if (match_extension(p->filename, c_mode_extensions)) + return 80; + + return 0; +} + +static int c_mode_init(EditState *s, ModeSavedData *saved_data) +{ + int ret; + + ret = text_mode_init(s, saved_data); + if (ret) + return ret; + set_colorize_func(s, c_colorize_line); + return ret; +} + +/* specific C mode commands */ static CmdDef c_commands[] = { CMD_( KEY_CTRL('i'), KEY_NONE, "c-indent-command", do_c_indent, "*") CMD_( KEY_META(KEY_CTRL('\\')), KEY_NONE, "c-indent-region", @@ -770,7 +791,6 @@ static int c_init(void) c_mode.mode_init = c_mode_init; qe_register_mode(&c_mode); - qe_register_cmd_table(c_commands, "C"); return 0; diff --git a/htmlsrc.c b/htmlsrc.c new file mode 100644 index 0000000..1e95939 --- /dev/null +++ b/htmlsrc.c @@ -0,0 +1,307 @@ +/* + * HTML Source mode for QEmacs. + * + * Copyright (c) 2000-2007 Charlie Gordon. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "qe.h" + +static const char *html_mode_extensions = "html|htm|asp|shtml|hta|htp|phtml"; + +static int get_html_entity(unsigned int *p) +{ + unsigned int *p_start, c; + + p_start = p; + c = (u8)*p; + + if (c != '&') + return 0; + + p++; + c = (u8)*p; + + if (c == '#') { + do { + p++; + c = (u8)*p; + } while (qe_isdigit(c)); + } else + if (qe_isalpha(c)) { + do { + p++; + c = (u8)*p; + } while (qe_isalnum(c)); + } else { + /* not an entity */ + return 0; + } + if (c == ';') { + p++; + } + return p - p_start; +} + +/* color colorization states */ +enum { + HTML_COMMENT = 0x01, /* */ + HTML_COMMENT1 = 0x02, /* */ + HTML_STRING = 0x04, /* " ... " */ + HTML_STRING1 = 0x08, /* ' ... ' */ + HTML_TAG = 0x10, /* */ + HTML_ENTITY = 0x20, /* &name[;] / {[;] */ + HTML_SCRIPTTAG = 0x40, /* */ +}; + +/* CG: Should rely on len instead of '\n' */ +static void htmlsrc_colorize_line(unsigned int *buf, int len, + int *colorize_state_ptr, int state_only) +{ + int c, state, js_state, l; + unsigned int *p, *p_start, *p_end; + + state = *colorize_state_ptr; + p = buf; + p_start = p; + p_end = p + len; + + /* Kludge for preprocessed html */ + if (*p == '#') { + p = p_end; + set_color(p_start, p, QE_STYLE_PREPROCESS); + goto the_end; + } + + while (p < p_end) { + p_start = p; + c = *p; + + if (c == '\n') + break; + + if (state & HTML_SCRIPTTAG) { + while (p < p_end) { + if (*p++ == '>') { + state = HTML_SCRIPT; + break; + } + } + set_color(p_start, p, QE_STYLE_HTML_SCRIPT); + continue; + } + if (state & HTML_SCRIPT) { + for (; p < p_end; p++) { + if (*p == '<' && ustristart(p, "", NULL)) + break; + } + js_state = state & ~HTML_SCRIPT; + c_colorize_line (p_start, p - p_start, + &js_state, state_only); + state = js_state | HTML_SCRIPT; + if (p < p_end) { + p_start = p; + p += strlen(""); + state = 0; + set_color(p_start, p, QE_STYLE_HTML_SCRIPT); + } + continue; + } + if (state & HTML_COMMENT) { + for (; p < p_end; p++) { + if (*p == '-' && p[1] == '-' + && p[2] == '>') { + p += 2; + state &= ~HTML_COMMENT; + break; + } + } + set_color(p_start, p, QE_STYLE_HTML_COMMENT); + continue; + } + if (state & HTML_COMMENT1) { + for (; p < p_end; p++) { + if (*p == '>') { + p++; + state &= ~HTML_COMMENT1; + break; + } + } + set_color(p_start, p, QE_STYLE_HTML_COMMENT); + continue; + } + if (state & HTML_ENTITY) { + if ((l = get_html_entity(p)) == 0) + p++; + else + p += l; + state &= ~HTML_ENTITY; + set_color(p_start, p, QE_STYLE_HTML_ENTITY); + continue; + } + if (state & (HTML_STRING|HTML_STRING1)) { + char delim = (char)((state & HTML_STRING1) ? '\'' : '\"'); + + for (; p < p_end; p++) { + if (*p == '&' && get_html_entity(p)) { + state |= HTML_ENTITY; + break; + } + if (*p == delim) { + p++; + state &= ~(HTML_STRING|HTML_STRING1); + break; + } + /* Premature end of string */ + if (*p == '>') { + state &= ~(HTML_STRING|HTML_STRING1); + break; + } + } + set_color(p_start, p, QE_STYLE_HTML_STRING); + continue; + } + if (state & HTML_TAG) { + for (; p < p_end; p++) { + if (*p == '&' && get_html_entity(p)) { + state |= HTML_ENTITY; + break; + } + if (*p == '\"') { + state |= HTML_STRING; + break; + } + if (*p == '\'') { + state |= HTML_STRING1; + break; + } + if (*p == '>') { + p++; + state &= ~HTML_TAG; + break; + } + } + set_color(p_start, p, QE_STYLE_HTML_TAG); + if (state & (HTML_STRING|HTML_STRING1)) { + set_color1(p, QE_STYLE_HTML_STRING); + p++; + } + continue; + } + /* Plain text stream */ + for (; p < p_end; p++) { + if (*p == '<' + && (qe_isalpha(p[1]) + || p[1] == '!' || p[1] == '/' || p[1] == '?')) { + //set_color(p_start, p, QE_STYLE_HTML_TEXT); + p_start = p; + if (ustristart (p, "buf; + + /* first check file extension */ + if (match_extension(p->filename, html_mode_extensions)) + return 80; + + /* then try buffer contents */ + if (p->buf_size >= 5 && + (!html_tagcmp(buf, " 0 && str[i - 1] == '\\') + break; + set_color(str + i, str + n, MAKEFILE_COMMENT); + i = n; + continue; + case '!': + /* case '.':*/ + if (i > 0) + break; + preprocess: + /* scan for comment */ + for (j = i + 1; j < n; j++) { + if (str[j] == '#') + break; + } + set_color(str + i, str + j, MAKEFILE_PREPROCESS); + i = j; + continue; + case '\'': + case '`': + case '"': + /* parse string const */ + for (j = i + 1; j < n; j++) { + if (str[j] == str[i]) { + j++; + break; + } + } + set_color(str + i, str + j, MAKEFILE_STRING); + i = j; + continue; + default: + break; + } + i++; + } +} + +#undef MAKEFILE_TEXT +#undef MAKEFILE_COMMENT +#undef MAKEFILE_STRING +#undef MAKEFILE_PREPROCESS +#undef MAKEFILE_VARIABLE +#undef MAKEFILE_TARGET +#undef MAKEFILE_MACRO + +static int makefile_mode_probe(ModeProbeData *p) +{ + const char *base = basename(p->filename); + + /* check file name or extension */ + if (match_extension(base, "mk|mak") + || stristart(base, "makefile", NULL)) + return 70; + + return 0; +} + +static int makefile_mode_init(EditState *s, ModeSavedData *saved_data) +{ + int ret; + + ret = text_mode_init(s, saved_data); + if (ret) + return ret; + set_colorize_func(s, makefile_colorize_line); + return ret; +} + +/* specific makefile commands */ +static CmdDef makefile_commands[] = { + CMD_DEF_END, +}; + +static ModeDef makefile_mode; + +static int makefile_init(void) +{ + /* c mode is almost like the text mode, so we copy and patch it */ + memcpy(&makefile_mode, &text_mode, sizeof(ModeDef)); + makefile_mode.name = "Makefile"; + makefile_mode.mode_probe = makefile_mode_probe; + makefile_mode.mode_init = makefile_mode_init; + + qe_register_mode(&makefile_mode); + qe_register_cmd_table(makefile_commands, "Makefile"); + + return 0; +} + +qe_module_init(makefile_init); diff --git a/perl.c b/perl.c new file mode 100644 index 0000000..6d94cdc --- /dev/null +++ b/perl.c @@ -0,0 +1,357 @@ +/* + * Perl Source mode for QEmacs. + * + * Copyright (c) 2000-2007 Charlie Gordon. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "qe.h" + +static const char *perl_mode_extensions = "pl|perl"; + +/*---------------- Perl colors ----------------*/ + +#define PERL_TEXT QE_STYLE_DEFAULT +#define PERL_COMMENT QE_STYLE_COMMENT +#define PERL_STRING QE_STYLE_STRING +#define PERL_REGEX QE_STYLE_STRING +#define PERL_DELIM QE_STYLE_KEYWORD +#define PERL_KEYWORD QE_STYLE_KEYWORD +#define PERL_VAR QE_STYLE_VARIABLE +#define PERL_NUMBER QE_STYLE_NUMBER + +#define IN_STRING1 0x01 /* single quote */ +#define IN_STRING2 0x02 /* double quote */ +#define IN_FORMAT 0x04 /* format = ... */ +#define IN_INPUT 0x08 + +/* CG: bogus if multiple regions are colorized */ +static unsigned int perl_eos[100]; +static int perl_eos_len; + +static int perl_var(const unsigned int *str, int j, int n) +{ + n = n; + + if (qe_isdigit(str[j])) + return j; + for (; j < n; j++) { + if (qe_isalnum(str[j]) || str[j] == '_') + continue; + if (str[j] == '\'' + && (qe_isalpha(str[j + 1]) || str[j + 1] == '_')) + j++; + else + break; + } + return j; +} + +static int perl_number(const unsigned int *str, int j, int n) +{ + n = n; + + if (str[j] == '0') { + j++; + if (str[j] == 'x' || str[j] == 'X') { + do j++; while (qe_isxdigit(str[j])); + return j; + } + if (str[j] >= '0' && str[j] <= '7') { + do j++; while (str[j] >= '0' && str[j] <= '7'); + return j; + } + } + while (qe_isdigit(str[j])) + j++; + + if (str[j] == '.') + do j++; while (qe_isdigit(str[j])); + + if (str[j] == 'E' || str[j] == 'e') { + j++; + if (str[j] == '-' || str[j] == '+') + j++; + while (qe_isdigit(str[j])) + j++; + } + return j; +} + +/* return offset of matching delimiter or end of string */ +static int perl_string(const unsigned int *str, unsigned int delim, int j, int n) +{ + for (; j < n; j++) { + if (str[j] == '\\') + j++; + else + if (str[j] == delim) + return j; + } + return j; +} + +static void perl_colorize_line(unsigned int *str, int n, int *statep, int state_only) +{ + int i = 0, c, c1, c2, j = i, s1, s2, delim = 0; + int colstate = *statep; + + if (colstate & (IN_STRING1|IN_STRING2)) { + delim = (colstate & IN_STRING1) ? '\'' : '\"'; + i = perl_string(str, delim, j, n); + if (i < n) { + i++; + colstate &= ~(IN_STRING1|IN_STRING2); + } + set_color(str + j, str + i, PERL_STRING); + } else + if (colstate & IN_FORMAT) { + i = n; + set_color(str + j, str + i, PERL_STRING); + if (n == 1 && str[0] == '.') + colstate &= ~IN_FORMAT; + } + if (colstate & IN_INPUT) { + //vdm_noRetrievalKey = 1; + i = n; + set_color(str + j, str + i, PERL_STRING); + if (n == perl_eos_len && !umemcmp(perl_eos, str, n)) + colstate &= ~IN_INPUT; + } + while (i < n) { + j = i + 1; + c1 = str[j]; + switch (c = str[i]) { + case '$': + if (c1 == '^' && qe_isalpha(str[i + 2])) { + j = i + 3; + goto keyword; + } + if (c1 == '#' + && (qe_isalpha(str[i + 2]) || str[i + 2] == '_')) + j++; + else + if (!qe_isalpha(c1) && c1 != '_') { + /* Special variable */ + j = i + 2; + goto keyword; + } + /* FALL THRU */ + case '*': + case '@': + case '%': + case '&': + if (j >= n) + break; + s1 = perl_var(str, j, n); + if (s1 > j) { + set_color(str + i, str + s1, PERL_VAR); + i = s1; + continue; + } + break; + case '-': + if (c1 == '-') { + i += 2; + continue; + } + if (qe_isalpha(c1) && !qe_isalnum(str[i + 2])) { + j = i + 2; + goto keyword; + } + break; + case '#': + set_color(str + i, str + n, PERL_COMMENT); + i = n; + continue; + case '<': + if (c1 == '<') { + /* Should check for unary context */ + s1 = i + 2; + c2 = str[s1]; + if (c2 == '"' || c2 == '\'' || c2 == '`') + s2 = perl_string(str, c2, ++s1, n); + else + s2 = perl_var(str, s1, n); + if (s2 > s1) { + umemcpy(perl_eos, str + s1, s2 - s1); + perl_eos_len = s2 - s1; + colstate |= IN_INPUT; + } + i += 2; + continue; + } + delim = '>'; + goto string; + case '/': + case '?': + /* Should check for unary context */ + /* parse regex */ + s1 = perl_string(str, c, j, n); + if (s1 >= n) + break; + set_color1(str + i, PERL_DELIM); + set_color(str + i + 1, str + s1, PERL_REGEX); + i = s1; + while (++i < n && qe_isalpha(str[i])) + continue; + set_color(str + s1, str + i, PERL_DELIM); + continue; + case '\'': + case '`': + case '"': + delim = c; + string: + /* parse string const */ + s1 = perl_string(str, delim, j, n); + if (s1 >= n) { + if (c == '\'') { + set_color(str + i, str + n, PERL_STRING); + i = n; + colstate |= IN_STRING1; + continue; + } + if (c == '\"') { + set_color(str + i, str + n, PERL_STRING); + i = n; + colstate |= IN_STRING2; + continue; + } + break; + } + s1++; + set_color(str + i, str + s1, PERL_STRING); + i = s1; + continue; + default: + if (qe_isdigit(c)) { + j = perl_number(str, i, n); + set_color(str + i, str + j, PERL_NUMBER); + i = j; + continue; + } + if (!qe_isalpha(c) && c != '_') + break; + + j = perl_var(str, i, n); + if (j == i) + break; + + if (j >= n) + goto keyword; + + /* Should check for context */ + if ((j == i + 1 && (c == 'm' || c == 'q')) + || (j == i + 2 && c == 'q' && (c1 == 'q' || c1 == 'x'))) { + s1 = perl_string(str, str[j], j + 1, n); + if (s1 >= n) + goto keyword; + set_color(str + i, str + j + 1, PERL_DELIM); + set_color(str + j + 1, str + s1, PERL_REGEX); + i = s1; + while (++i < n && qe_isalpha(str[i])) + continue; + set_color(str + s1, str + i, PERL_DELIM); + continue; + } + /* Should check for context */ + if ((j == i + 1 && (c == 's' /* || c == 'y' */)) + || (j == i + 2 && c == 't' && c1 == 'r')) { + s1 = perl_string(str, str[j], j + 1, n); + if (s1 >= n) + goto keyword; + s2 = perl_string(str, str[j], s1 + 1, n); + if (s2 >= n) + goto keyword; + set_color(str + i, str + j + 1, PERL_DELIM); + set_color(str + j + 1, str + s1, PERL_REGEX); + set_color1(str + s1, PERL_DELIM); + set_color(str + s1 + 1, str + s2, PERL_REGEX); + i = s2; + while (++i < n && qe_isalpha(str[i])) + continue; + set_color(str + s2, str + i, PERL_DELIM); + continue; + } + keyword: + if (j - i == 6 && ustristart(str + i, "format", NULL)) + colstate |= IN_FORMAT; + set_color(str + i, str + j, PERL_KEYWORD); + i = j; + continue; + } + i++; + continue; + } + *statep = colstate; +} + +#undef PERL_TEXT +#undef PERL_COMMENT +#undef PERL_STRING +#undef PERL_REGEX +#undef PERL_DELIM +#undef PERL_KEYWORD +#undef PERL_VAR +#undef PERL_NUMBER + +#undef IN_STRING1 +#undef IN_STRING2 +#undef IN_FORMAT +#undef IN_INPUT + +static int perl_mode_probe(ModeProbeData *p) +{ + /* just check file extension */ + if (match_extension(p->filename, perl_mode_extensions)) + return 80; + + return 0; +} + +static int perl_mode_init(EditState *s, ModeSavedData *saved_data) +{ + int ret; + + ret = text_mode_init(s, saved_data); + if (ret) + return ret; + set_colorize_func(s, perl_colorize_line); + return ret; +} + +/* specific perl commands */ +static CmdDef perl_commands[] = { + CMD_DEF_END, +}; + +static ModeDef perl_mode; + +static int perl_init(void) +{ + /* c mode is almost like the text mode, so we copy and patch it */ + memcpy(&perl_mode, &text_mode, sizeof(ModeDef)); + perl_mode.name = "Perl"; + perl_mode.mode_probe = perl_mode_probe; + perl_mode.mode_init = perl_mode_init; + + qe_register_mode(&perl_mode); + qe_register_cmd_table(perl_commands, "Perl"); + + return 0; +} + +qe_module_init(perl_init); diff --git a/qestyles.h b/qestyles.h index e648293..2e92fd8 100644 --- a/qestyles.h +++ b/qestyles.h @@ -62,3 +62,20 @@ STYLE_DEF(QE_STYLE_CSS, "css", QERGB(0x98, 0xf8, 0x98), COLOR_TRANSPARENT, 0, 0) + + /* HTML coloring styles */ + STYLE_DEF(QE_STYLE_HTML_COMMENT, "html-comment", + QERGB(0xf8, 0x44, 0x00), QERGB(0x00, 0x00, 0x00), + 0, 0) + STYLE_DEF(QE_STYLE_HTML_STRING, "html-string", + QERGB(0xf8, 0xa0, 0x78), QERGB(0x00, 0x00, 0x00), + 0, 0) + STYLE_DEF(QE_STYLE_HTML_SCRIPT, "html-script", + QERGB(0x98, 0xf8, 0x98), QERGB(0x00, 0x00, 0x00), + 0, 0) + STYLE_DEF(QE_STYLE_HTML_ENTITY, "html-entity", + QERGB(0xe8, 0xdc, 0x80), QERGB(0x00, 0x00, 0x00), + 0, 0) + STYLE_DEF(QE_STYLE_HTML_TAG, "html-tag", + QERGB(0x80, 0xcc, 0xf0), QERGB(0x00, 0x00, 0x00), + 0, 0)