static const char * xx_strchr (WEdit * edit, const unsigned char *s, int char_byte) { while (*s >= '\005' && xx_tolower (edit, *s) != char_byte) s++; return (const char *) s; }
static struct syntax_rule apply_rules_going_right (WEdit * edit, long i, struct syntax_rule rule) { struct context_rule *r; int c; gboolean contextchanged = FALSE; gboolean found_left = FALSE, found_right = FALSE; gboolean keyword_foundleft = FALSE, keyword_foundright = FALSE; gboolean is_end; long end = 0; struct syntax_rule _rule = rule; c = xx_tolower (edit, edit_get_byte (edit, i)); if (c == 0) return rule; is_end = (rule.end == (unsigned char) i); /* check to turn off a keyword */ if (_rule.keyword) { if (edit_get_byte (edit, i - 1) == '\n') _rule.keyword = 0; if (is_end) { _rule.keyword = 0; keyword_foundleft = TRUE; } } /* check to turn off a context */ if (_rule.context && !_rule.keyword) { long e; r = edit->rules[_rule.context]; if (r->first_right == c && !(rule.border & RULE_ON_RIGHT_BORDER) && (e = compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) > 0) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_RIGHT_BORDER; if (r->between_delimiters) _rule.context = 0; } else if (is_end && rule.border & RULE_ON_RIGHT_BORDER) { /* always turn off a context at 4 */ found_left = TRUE; _rule.border = 0; if (!keyword_foundleft) _rule.context = 0; } else if (is_end && rule.border & RULE_ON_LEFT_BORDER) { /* never turn off a context at 2 */ found_left = TRUE; _rule.border = 0; } } /* check to turn on a keyword */ if (!_rule.keyword) { const char *p; r = edit->rules[_rule.context]; p = r->keyword_first_chars; if (p != NULL) while (*(p = xx_strchr (edit, (unsigned char *) p + 1, c)) != '\0') { struct key_word *k; int count; long e; count = p - r->keyword_first_chars; k = r->keyword[count]; e = compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start); if (e > 0) { end = e; _rule.end = e; _rule.keyword = count; keyword_foundright = TRUE; break; } } } /* check to turn on a context */ if (!_rule.context) { if (!found_left && is_end) { if (rule.border & RULE_ON_RIGHT_BORDER) { _rule.border = 0; _rule.context = 0; contextchanged = TRUE; _rule.keyword = 0; } else if (rule.border & RULE_ON_LEFT_BORDER) { r = edit->rules[_rule._context]; _rule.border = 0; if (r->between_delimiters) { _rule.context = _rule._context; contextchanged = TRUE; _rule.keyword = 0; if (r->first_right == c) { long e; e = compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right); if (e >= end) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_RIGHT_BORDER; _rule.context = 0; } } } } } if (!found_right) { int count; struct context_rule **rules = edit->rules; for (count = 1; rules[count]; count++) { r = rules[count]; if (r->first_left == c) { long e; e = compare_word_to_right (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left); if (e >= end && (!_rule.keyword || keyword_foundright)) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_LEFT_BORDER; _rule._context = count; if (!r->between_delimiters && !_rule.keyword) { _rule.context = count; contextchanged = TRUE; } break; } } } } } /* check again to turn on a keyword if the context switched */ if (contextchanged && !_rule.keyword) { const char *p; r = edit->rules[_rule.context]; p = r->keyword_first_chars; while (*(p = xx_strchr (edit, (unsigned char *) p + 1, c)) != '\0') { struct key_word *k; int count; long e; count = p - r->keyword_first_chars; k = r->keyword[count]; e = compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start); if (e > 0) { _rule.end = e; _rule.keyword = count; break; } } } return _rule; }
static void apply_rules_going_right (WEdit * edit, off_t i) { context_rule_t *r; int c; gboolean contextchanged = FALSE; gboolean found_left = FALSE, found_right = FALSE; gboolean keyword_foundleft = FALSE, keyword_foundright = FALSE; gboolean is_end; off_t end = 0; edit_syntax_rule_t _rule = edit->rule; c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i)); if (c == 0) return; is_end = (edit->rule.end == i); /* check to turn off a keyword */ if (_rule.keyword != 0) { if (edit_buffer_get_byte (&edit->buffer, i - 1) == '\n') _rule.keyword = 0; if (is_end) { _rule.keyword = 0; keyword_foundleft = TRUE; } } /* check to turn off a context */ if (_rule.context != 0 && _rule.keyword == 0) { off_t e; r = CONTEXT_RULE (g_ptr_array_index (edit->rules, _rule.context)); if (r->first_right == c && (edit->rule.border & RULE_ON_RIGHT_BORDER) == 0 && (e = compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) > 0) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_RIGHT_BORDER; if (r->between_delimiters) _rule.context = 0; } else if (is_end && (edit->rule.border & RULE_ON_RIGHT_BORDER) != 0) { /* always turn off a context at 4 */ found_left = TRUE; _rule.border = 0; if (!keyword_foundleft) _rule.context = 0; } else if (is_end && (edit->rule.border & RULE_ON_LEFT_BORDER) != 0) { /* never turn off a context at 2 */ found_left = TRUE; _rule.border = 0; } } /* check to turn on a keyword */ if (_rule.keyword == 0) { const char *p; r = CONTEXT_RULE (g_ptr_array_index (edit->rules, _rule.context)); p = r->keyword_first_chars; if (p != NULL) while (*(p = xx_strchr (edit, (const unsigned char *) p + 1, c)) != '\0') { syntax_keyword_t *k; int count; off_t e; count = p - r->keyword_first_chars; k = SYNTAX_KEYWORD (g_ptr_array_index (r->keyword, count)); e = compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start); if (e > 0) { /* when both context and keyword terminate with a newline, the context overflows to the next line and colorizes it incorrectly */ if (e > i + 1 && _rule._context != 0 && k->keyword[strlen (k->keyword) - 1] == '\n') { r = CONTEXT_RULE (g_ptr_array_index (edit->rules, _rule._context)); if (r->right != NULL && r->right[0] != '\0' && r->right[strlen (r->right) - 1] == '\n') e--; } end = e; _rule.end = e; _rule.keyword = count; keyword_foundright = TRUE; break; } } } /* check to turn on a context */ if (_rule.context == 0) { if (!found_left && is_end) { if ((edit->rule.border & RULE_ON_RIGHT_BORDER) != 0) { _rule.border = 0; _rule.context = 0; contextchanged = TRUE; _rule.keyword = 0; } else if ((edit->rule.border & RULE_ON_LEFT_BORDER) != 0) { r = CONTEXT_RULE (g_ptr_array_index (edit->rules, _rule._context)); _rule.border = 0; if (r->between_delimiters) { _rule.context = _rule._context; contextchanged = TRUE; _rule.keyword = 0; if (r->first_right == c) { off_t e; e = compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right); if (e >= end) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_RIGHT_BORDER; _rule.context = 0; } } } } } if (!found_right) { size_t count; for (count = 1; count < edit->rules->len; count++) { r = CONTEXT_RULE (g_ptr_array_index (edit->rules, count)); if (r->first_left == c) { off_t e; e = compare_word_to_right (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left); if (e >= end && (_rule.keyword == 0 || keyword_foundright)) { _rule.end = e; found_right = TRUE; _rule.border = RULE_ON_LEFT_BORDER; _rule._context = count; if (!r->between_delimiters && _rule.keyword == 0) { _rule.context = count; contextchanged = TRUE; } break; } } } } } /* check again to turn on a keyword if the context switched */ if (contextchanged && _rule.keyword == 0) { const char *p; r = CONTEXT_RULE (g_ptr_array_index (edit->rules, _rule.context)); p = r->keyword_first_chars; while (*(p = xx_strchr (edit, (const unsigned char *) p + 1, c)) != '\0') { syntax_keyword_t *k; int count; off_t e; count = p - r->keyword_first_chars; k = SYNTAX_KEYWORD (g_ptr_array_index (r->keyword, count)); e = compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start); if (e > 0) { _rule.end = e; _rule.keyword = count; break; } } } edit->rule = _rule; }
static long compare_word_to_right (WEdit * edit, long i, const char *text, const char *whole_left, const char *whole_right, int line_start) { const unsigned char *p, *q; int c, d, j; if (*text == '\0') return -1; c = xx_tolower (edit, edit_get_byte (edit, i - 1)); if (line_start != 0 && c != '\n') return -1; if (whole_left != NULL && strchr (whole_left, c) != NULL) return -1; for (p = (unsigned char *) text, q = p + str_term_width1 ((char *) p); p < q; p++, i++) { switch (*p) { case SYNTAX_TOKEN_STAR: if (++p > q) return -1; for (;;) { c = xx_tolower (edit, edit_get_byte (edit, i)); if (*p == '\0' && whole_right != NULL && strchr (whole_right, c) == NULL) break; if (c == *p) break; if (c == '\n') return -1; i++; } break; case SYNTAX_TOKEN_PLUS: if (++p > q) return -1; j = 0; for (;;) { c = xx_tolower (edit, edit_get_byte (edit, i)); if (c == *p) { j = i; if (*p == *text && p[1] == '\0') /* handle eg '+' and @+@ keywords properly */ break; } if (j && strchr ((char *) p + 1, c)) /* c exists further down, so it will get matched later */ break; if (c == '\n' || c == '\t' || c == ' ') { if (!*p) { i--; break; } if (j == 0) return -1; i = j; break; } if (whole_right != NULL && (strchr (whole_right, c) == NULL)) { if (*p == '\0') { i--; break; } if (j == 0) return -1; i = j; break; } i++; } break; case SYNTAX_TOKEN_BRACKET: if (++p > q) return -1; c = -1; for (;; i++) { d = c; c = xx_tolower (edit, edit_get_byte (edit, i)); for (j = 0; p[j] != SYNTAX_TOKEN_BRACKET && p[j]; j++) if (c == p[j]) goto found_char2; break; found_char2: ; /* dummy command */ } i--; while (*p != SYNTAX_TOKEN_BRACKET && p <= q) p++; if (p > q) return -1; if (p[1] == d) i--; break; case SYNTAX_TOKEN_BRACE: if (++p > q) return -1; c = xx_tolower (edit, edit_get_byte (edit, i)); for (; *p != SYNTAX_TOKEN_BRACE && *p; p++) if (c == *p) goto found_char3; return -1; found_char3: while (*p != SYNTAX_TOKEN_BRACE && p < q) p++; break; default: if (*p != xx_tolower (edit, edit_get_byte (edit, i))) return -1; } } if (whole_right != NULL && strchr (whole_right, xx_tolower (edit, edit_get_byte (edit, i))) != NULL) return -1; return i; }
static off_t compare_word_to_right (const WEdit * edit, off_t i, const char *text, const char *whole_left, const char *whole_right, gboolean line_start) { const unsigned char *p, *q; int c, d, j; if (*text == '\0') return -1; c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i - 1)); if ((line_start && c != '\n') || (whole_left != NULL && strchr (whole_left, c) != NULL)) return -1; for (p = (const unsigned char *) text, q = p + strlen ((const char *) p); p < q; p++, i++) { switch (*p) { case SYNTAX_TOKEN_STAR: if (++p > q) return -1; while (TRUE) { c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i)); if (*p == '\0' && whole_right != NULL && strchr (whole_right, c) == NULL) break; if (c == *p) break; if (c == '\n') return -1; i++; } break; case SYNTAX_TOKEN_PLUS: if (++p > q) return -1; j = 0; while (TRUE) { c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i)); if (c == *p) { j = i; if (p[0] == text[0] && p[1] == '\0') /* handle eg '+' and @+@ keywords properly */ break; } if (j != 0 && strchr ((const char *) p + 1, c) != NULL) /* c exists further down, so it will get matched later */ break; if (whiteness (c) || (whole_right != NULL && strchr (whole_right, c) == NULL)) { if (*p == '\0') { i--; break; } if (j == 0) return -1; i = j; break; } i++; } break; case SYNTAX_TOKEN_BRACKET: if (++p > q) return -1; c = -1; while (TRUE) { d = c; c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i)); for (j = 0; p[j] != SYNTAX_TOKEN_BRACKET && p[j] != '\0'; j++) if (c == p[j]) goto found_char2; break; found_char2: i++; } i--; while (*p != SYNTAX_TOKEN_BRACKET && p <= q) p++; if (p > q) return -1; if (p[1] == d) i--; break; case SYNTAX_TOKEN_BRACE: if (++p > q) return -1; c = xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i)); for (; *p != SYNTAX_TOKEN_BRACE && *p != '\0'; p++) if (c == *p) goto found_char3; return -1; found_char3: while (*p != SYNTAX_TOKEN_BRACE && p < q) p++; break; default: if (*p != xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i))) return -1; } } return (whole_right != NULL && strchr (whole_right, xx_tolower (edit, edit_buffer_get_byte (&edit->buffer, i))) != NULL) ? -1 : i; }