📄 syntax.c
字号:
/* editor syntax highlighting.
Copyright (C) 1996, 1997, 1998 the Free Software Foundation
Authors: 1998 Paul Sheer
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
#ifdef MIDNIGHT
#include "edit.h"
#else
#include "coolwidget.h"
#endif
#if !defined(MIDNIGHT) || defined(HAVE_SYNTAXH)
int option_syntax_highlighting = 1;
/* these three functions are called from the outside */
void edit_load_syntax (WEdit * edit, char **names, char *type);
void edit_free_syntax_rules (WEdit * edit);
void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg);
static void *syntax_malloc (size_t x)
{
void *p;
p = malloc (x);
memset (p, 0, x);
return p;
}
#define syntax_free(x) {if(x){free(x);(x)=0;}}
static int compare_word_to_right (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
{
char *p;
int c, j;
if (!*text)
return 0;
c = edit_get_byte (edit, i - 1);
if (line_start)
if (c != '\n')
return 0;
if (whole_left)
if (strchr (whole_left, c))
return 0;
for (p = text; *p; p++, i++) {
switch (*p) {
case '\001':
p++;
for (;;) {
c = edit_get_byte (edit, i);
if (c == *p)
break;
if (c == '\n')
return 0;
i++;
}
break;
case '\002':
p++;
for (;;) {
c = edit_get_byte (edit, i);
if (c == *p)
break;
if (c == '\n' || c == '\t' || c == ' ')
return 0;
i++;
}
break;
case '\003':
p++;
#if 0
c = edit_get_byte (edit, i++);
for (j = 0; p[j] != '\003'; j++)
if (c == p[j])
goto found_char1;
return 0;
found_char1:
#endif
for (;;i++) {
c = edit_get_byte (edit, i);
for (j = 0; p[j] != '\003'; j++)
if (c == p[j])
goto found_char2;
break;
found_char2:;
}
i--;
while (*p != '\003')
p++;
break;
#if 0
case '\004':
p++;
c = edit_get_byte (edit, i++);
for (j = 0; p[j] != '\004'; j++)
if (c == p[j])
return 0;
for (;;i++) {
c = edit_get_byte (edit, i);
for (j = 0; p[j] != '\004'; j++)
if (c == p[j])
goto found_char4;
continue;
found_char4:
break;
}
i--;
while (*p != '\004')
p++;
break;
#endif
default:
if (*p != edit_get_byte (edit, i))
return 0;
}
}
if (whole_right)
if (strchr (whole_right, edit_get_byte (edit, i)))
return 0;
return 1;
}
static int compare_word_to_left (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
{
char *p;
int c, j;
#if 0
int d;
#endif
if (!*text)
return 0;
if (whole_right)
if (strchr (whole_right, edit_get_byte (edit, i + 1)))
return 0;
for (p = text + strlen (text) - 1; (unsigned long) p >= (unsigned long) text; p--, i--) {
switch (*p) {
case '\001':
p--;
for (;;) {
c = edit_get_byte (edit, i);
if (c == *p)
break;
if (c == '\n')
return 0;
i--;
}
break;
case '\002':
p--;
for (;;) {
c = edit_get_byte (edit, i);
if (c == *p)
break;
if (c == '\n' || c == '\t' || c == ' ')
return 0;
i--;
}
break;
case '\003':
while (*(--p) != '\003');
p++;
#if 0
c = edit_get_byte (edit, i--);
for (j = 0; p[j] != '\003'; j++)
if (c == p[j])
goto found_char1;
return 0;
found_char1:
#endif
for (;; i--) {
c = edit_get_byte (edit, i);
for (j = 0; p[j] != '\003'; j++)
if (c == p[j])
goto found_char2;
break;
found_char2:;
}
i++;
p--;
break;
#if 0
case '\004':
while (*(--p) != '\004');
d = *p;
p++;
c = edit_get_byte (edit, i--);
for (j = 0; p[j] != '\004'; j++)
if (c == p[j])
return 0;
for (;; i--) {
c = edit_get_byte (edit, i);
for (j = 0; p[j] != '\004'; j++)
if (c == p[j] || c == '\n' || c == d)
goto found_char4;
continue;
found_char4:
break;
}
i++;
p--;
break;
#endif
default:
if (*p != edit_get_byte (edit, i))
return 0;
}
}
c = edit_get_byte (edit, i);
if (line_start)
if (c != '\n')
return 0;
if (whole_left)
if (strchr (whole_left, c))
return 0;
return 1;
}
#if 0
#define debug_printf(x,y) fprintf(stderr,x,y)
#else
#define debug_printf(x,y)
#endif
static inline unsigned long apply_rules_going_right (WEdit * edit, long i, unsigned long rule)
{
struct context_rule *r;
int context, contextchanged = 0, keyword, c1, c2;
int found_right = 0, found_left = 0, keyword_foundleft = 0;
int done = 0;
unsigned long border;
context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
border = rule & (RULE_ON_LEFT_BORDER | RULE_ON_RIGHT_BORDER);
c1 = edit_get_byte (edit, i - 1);
c2 = edit_get_byte (edit, i);
if (!c2 || !c1)
return rule;
debug_printf ("%c->", c1);
debug_printf ("%c ", c2);
/* check to turn off a keyword */
if (keyword) {
struct key_word *k;
k = edit->rules[context]->keyword[keyword];
if (c1 == '\n')
keyword = 0;
if (k->last == c1 && compare_word_to_left (edit, i - 1, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
keyword = 0;
keyword_foundleft = 1;
debug_printf ("keyword=%d ", keyword);
}
}
debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
/* check to turn off a context */
if (context && !keyword) {
r = edit->rules[context];
if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
&&!(rule & RULE_ON_RIGHT_BORDER)) {
debug_printf ("A:3 ", 0);
found_right = 1;
border = RULE_ON_RIGHT_BORDER;
if (r->between_delimiters)
context = 0;
} else if (!found_left) {
if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
&&(rule & RULE_ON_RIGHT_BORDER)) {
/* always turn off a context at 4 */
debug_printf ("A:4 ", 0);
found_left = 1;
border = 0;
if (!keyword_foundleft)
context = 0;
} else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
&&(rule & RULE_ON_LEFT_BORDER)) {
/* never turn off a context at 2 */
debug_printf ("A:2 ", 0);
found_left = 1;
border = 0;
}
}
}
debug_printf ("\n", 0);
/* check to turn on a keyword */
if (!keyword) {
char *p;
p = (r = edit->rules[context])->keyword_first_chars;
while ((p = strchr (p + 1, c2))) {
struct key_word *k;
int count;
count = (unsigned long) p - (unsigned long) r->keyword_first_chars;
k = r->keyword[count];
if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
keyword = count;
debug_printf ("keyword=%d ", keyword);
break;
}
}
}
/* check to turn on a context */
if (!context) {
int count;
for (count = 1; edit->rules[count] && !done; count++) {
r = edit->rules[count];
if (!found_left) {
if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
&&(rule & RULE_ON_RIGHT_BORDER)) {
debug_printf ("B:4 count=%d", count);
found_left = 1;
border = 0;
context = 0;
contextchanged = 1;
keyword = 0;
} else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
&&(rule & RULE_ON_LEFT_BORDER)) {
debug_printf ("B:2 ", 0);
found_left = 1;
border = 0;
if (r->between_delimiters) {
context = count;
contextchanged = 1;
keyword = 0;
debug_printf ("context=%d ", context);
if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) {
debug_printf ("B:3 ", 0);
found_right = 1;
border = RULE_ON_RIGHT_BORDER;
context = 0;
}
}
break;
}
}
if (!found_right) {
if (r->first_left == c2 && compare_word_to_right (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left)) {
debug_printf ("B:1 ", 0);
found_right = 1;
border = RULE_ON_LEFT_BORDER;
if (!r->between_delimiters) {
debug_printf ("context=%d ", context);
if (!keyword)
context = count;
}
break;
}
}
}
}
if (!keyword && contextchanged) {
char *p;
p = (r = edit->rules[context])->keyword_first_chars;
while ((p = strchr (p + 1, c2))) {
struct key_word *k;
int coutner;
coutner = (unsigned long) p - (unsigned long) r->keyword_first_chars;
k = r->keyword[coutner];
if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
keyword = coutner;
debug_printf ("keyword=%d ", keyword);
break;
}
}
}
debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
debug_printf ("keyword=%d ", keyword);
debug_printf (" %d#\n\n", context);
return (context << RULE_CONTEXT_SHIFT) | (keyword << RULE_WORD_SHIFT) | border;
}
static inline int resolve_left_delim (WEdit * edit, long i, struct context_rule *r, int s)
{
int c, count;
if (!r->conflicts)
return s;
for (;;) {
c = edit_get_byte (edit, i);
if (c == '\n')
break;
for (count = 1; r->conflicts[count]; count++) {
struct context_rule *p;
p = edit->rules[r->conflicts[count]];
if (!p)
break;
if (p->first_left == c && r->between_delimiters == p->between_delimiters && compare_word_to_right (edit, i, p->left, p->whole_word_chars_left, r->whole_word_chars_right, p->line_start_left))
return r->conflicts[count];
}
i--;
}
return 0;
}
static inline unsigned long apply_rules_going_left (WEdit * edit, long i, unsigned long rule)
{
struct context_rule *r;
int context, contextchanged = 0, keyword, c2, c1;
int found_left = 0, found_right = 0, keyword_foundright = 0;
int done = 0;
unsigned long border;
context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
border = rule & (RULE_ON_RIGHT_BORDER | RULE_ON_LEFT_BORDER);
c1 = edit_get_byte (edit, i);
c2 = edit_get_byte (edit, i + 1);
if (!c2 || !c1)
return rule;
debug_printf ("%c->", c2);
debug_printf ("%c ", c1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -