added Perl mode: perl.c
added Makefile mode: makemode.c
added HTML source mode: htmlsrc.c
added more dependencies in Makefile
added styles for HTML source coloring:
html-comment, html-string, html-script, html-entity, html-tag
no longer rely on \n at end of line in c_colorize_line
This commit is contained in:
parent
2d70f198fb
commit
fa760147c8
6 changed files with 959 additions and 64 deletions
17
Makefile
17
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
|
||||
|
|
|
|||
134
clang.c
134
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;
|
||||
|
|
|
|||
307
htmlsrc.c
Normal file
307
htmlsrc.c
Normal file
|
|
@ -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, /* <tag ... > */
|
||||
HTML_ENTITY = 0x20, /* &name[;] / {[;] */
|
||||
HTML_SCRIPTTAG = 0x40, /* <SCRIPT ...> */
|
||||
HTML_SCRIPT = 0x80, /* <SCRIPT> [...] </SCRIPT> */
|
||||
};
|
||||
|
||||
/* 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, "</script>", 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("</script>");
|
||||
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, "<script", NULL)) {
|
||||
state |= HTML_SCRIPTTAG;
|
||||
break;
|
||||
}
|
||||
if (p[1] == '!') {
|
||||
state |= HTML_COMMENT1;
|
||||
p += 2;
|
||||
if (*p == '-' && p[1] == '-') {
|
||||
p += 2;
|
||||
state |= HTML_COMMENT;
|
||||
}
|
||||
set_color(p_start, p, QE_STYLE_HTML_COMMENT);
|
||||
p_start = p;
|
||||
} else
|
||||
state |= HTML_TAG;
|
||||
break;
|
||||
}
|
||||
if (*p == '&' && get_html_entity (p)) {
|
||||
state |= HTML_ENTITY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//set_color(p_start, p - p_start, QE_STYLE_HTML_TEXT);
|
||||
}
|
||||
the_end:
|
||||
*colorize_state_ptr = state;
|
||||
}
|
||||
|
||||
static int html_tagcmp(const char *s1, const char *s2)
|
||||
{
|
||||
int d;
|
||||
|
||||
while (*s2) {
|
||||
d = *s2 - qe_toupper(*s1);
|
||||
if (d)
|
||||
return d;
|
||||
s2++;
|
||||
s1++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int htmlsrc_mode_probe(ModeProbeData *p)
|
||||
{
|
||||
const char *buf = (const char*)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, "<HTML") ||
|
||||
!html_tagcmp(buf, "<SCRIPT") ||
|
||||
!html_tagcmp(buf, "<?XML") ||
|
||||
!html_tagcmp(buf, "<!DOCTYPE"))) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int htmlsrc_mode_init(EditState *s, ModeSavedData *saved_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = text_mode_init(s, saved_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
set_colorize_func(s, htmlsrc_colorize_line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* specific htmlsrc commands */
|
||||
/* CG: need move / kill by tag level */
|
||||
static CmdDef htmlsrc_commands[] = {
|
||||
CMD_DEF_END,
|
||||
};
|
||||
|
||||
static ModeDef htmlsrc_mode;
|
||||
|
||||
static int htmlsrc_init(void)
|
||||
{
|
||||
/* c mode is almost like the text mode, so we copy and patch it */
|
||||
memcpy(&htmlsrc_mode, &text_mode, sizeof(ModeDef));
|
||||
htmlsrc_mode.name = "html-src";
|
||||
htmlsrc_mode.mode_probe = htmlsrc_mode_probe;
|
||||
htmlsrc_mode.mode_init = htmlsrc_mode_init;
|
||||
|
||||
qe_register_mode(&htmlsrc_mode);
|
||||
qe_register_cmd_table(htmlsrc_commands, "html-src");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qe_module_init(htmlsrc_init);
|
||||
191
makemode.c
Normal file
191
makemode.c
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Makefile 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"
|
||||
|
||||
/*---------------- Makefile colors ----------------*/
|
||||
|
||||
#define MAKEFILE_TEXT QE_STYLE_DEFAULT
|
||||
#define MAKEFILE_COMMENT QE_STYLE_COMMENT
|
||||
#define MAKEFILE_STRING QE_STYLE_STRING
|
||||
#define MAKEFILE_PREPROCESS QE_STYLE_PREPROCESS
|
||||
#define MAKEFILE_TARGET QE_STYLE_FUNCTION
|
||||
#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)
|
||||
{
|
||||
int i, j, level;
|
||||
|
||||
i = j = 0;
|
||||
|
||||
/* CG: should check for end of word */
|
||||
if (str[0] == 'i') {
|
||||
if (ustristart(str, "ifeq", NULL)
|
||||
|| ustristart(str, "ifneq", NULL)
|
||||
|| ustristart(str, "ifdef", NULL)
|
||||
|| ustristart(str, "ifndef", NULL)
|
||||
|| ustristart(str, "include", NULL))
|
||||
goto preprocess;
|
||||
} else
|
||||
if (str[0] == 'e') {
|
||||
if (ustristart(str, "else", NULL)
|
||||
|| ustristart(str, "endif", NULL))
|
||||
goto preprocess;
|
||||
}
|
||||
|
||||
while (i < n) {
|
||||
switch (str[i]) {
|
||||
case '$':
|
||||
i += 1;
|
||||
j = i + 1;
|
||||
if (str[i] == '(') {
|
||||
i += 1;
|
||||
level = 1;
|
||||
for (j = i; j < n; j++) {
|
||||
if (str[j] == '(')
|
||||
level++;
|
||||
if (str[j] == ')' && --level <= 0)
|
||||
break;
|
||||
if (str[j] == ' ' || str[j] == '$') {
|
||||
/* should have function color */
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i < j)
|
||||
set_color(str + i, str + j, MAKEFILE_MACRO);
|
||||
i = j;
|
||||
continue;
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (i == 0)
|
||||
j = 1;
|
||||
break;
|
||||
case '+':
|
||||
if (!j && str[i+1] == '=')
|
||||
goto variable;
|
||||
case ':':
|
||||
if (j)
|
||||
break;
|
||||
if (str[i+1] == '=')
|
||||
goto variable;
|
||||
set_color(str + j, str + i, MAKEFILE_TARGET);
|
||||
break;
|
||||
case '=':
|
||||
if (j)
|
||||
break;
|
||||
variable:
|
||||
set_color(str + j, str + i, MAKEFILE_VARIABLE);
|
||||
break;
|
||||
case '#':
|
||||
if (i > 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);
|
||||
357
perl.c
Normal file
357
perl.c
Normal file
|
|
@ -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);
|
||||
17
qestyles.h
17
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue