⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syntax.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 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 + -