static inline void put_paragraph (WEdit * edit, unsigned char *t, off_t p, long indent, off_t size) { off_t cursor; off_t i; int c = '\0'; cursor = edit->buffer.curs1; if (indent != 0) while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL) p++; for (i = 0; i < size; i++, p++) { if (i != 0 && indent != 0) { if (t[i - 1] == '\n' && c == '\n') { while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL) p++; } else if (t[i - 1] == '\n') { off_t curs; edit_cursor_move (edit, p - edit->buffer.curs1); curs = edit->buffer.curs1; edit_insert_indent (edit, indent); if (cursor >= curs) cursor += edit->buffer.curs1 - p; p = edit->buffer.curs1; } else if (c == '\n') { edit_cursor_move (edit, p - edit->buffer.curs1); while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL) { edit_delete (edit, TRUE); if (cursor > edit->buffer.curs1) cursor--; } p = edit->buffer.curs1; } } c = edit_buffer_get_byte (&edit->buffer, p); if (c != t[i]) replace_at (edit, p, t[i]); } edit_cursor_move (edit, cursor - edit->buffer.curs1); /* restore cursor position */ }
static GString * get_paragraph (const edit_buffer_t * buf, off_t p, off_t q, gboolean indent) { GString *t; t = g_string_sized_new (128); for (; p < q; p++) { if (indent && edit_buffer_get_byte (buf, p - 1) == '\n') while (strchr ("\t ", edit_buffer_get_byte (buf, p)) != NULL) p++; g_string_append_c (t, edit_buffer_get_byte (buf, p)); } g_string_append_c (t, '\n'); return t; }
static gboolean bad_line_start (const edit_buffer_t * buf, off_t p) { int c; c = edit_buffer_get_byte (buf, p); if (c == '.') { /* `...' is acceptable */ return !(edit_buffer_get_byte (buf, p + 1) == '.' && edit_buffer_get_byte (buf, p + 2) == '.'); } if (c == '-') { /* `---' is acceptable */ return !(edit_buffer_get_byte (buf, p + 1) == '-' && edit_buffer_get_byte (buf, p + 2) == '-'); } return (option_stop_format_chars != NULL && strchr (option_stop_format_chars, c) != NULL); }
static long edit_indent_width (const WEdit * edit, off_t p) { off_t q = p; /* move to the end of the leading whitespace of the line */ while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, q)) != NULL && q < edit->buffer.size - 1) q++; /* count the number of columns of indentation */ return (long) edit_move_forward3 (edit, p, 0, q); }
static inline long test_indent (const WEdit * edit, off_t p, off_t q) { long indent; indent = edit_indent_width (edit, p++); if (indent == 0) return 0; for (; p < q; p++) if (edit_buffer_get_byte (&edit->buffer, p - 1) == '\n' && indent != edit_indent_width (edit, p)) return 0; return indent; }
static off_t line_start (const edit_buffer_t * buf, long line) { off_t p; long l; l = buf->curs_line; p = buf->curs1; if (line < l) p = edit_buffer_move_backward (buf, p, l - line); else if (line > l) p = edit_buffer_move_forward (buf, p, line - l, 0); p = edit_buffer_get_bol (buf, p); while (strchr ("\t ", edit_buffer_get_byte (buf, p)) != NULL) p++; return p; }
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 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; }
static void edit_draw_this_line (WEdit * edit, off_t b, long row, long start_col, long end_col) { Widget *w = WIDGET (edit); struct line_s line[MAX_LINE_LEN]; struct line_s *p = line; off_t m1 = 0, m2 = 0, q; int col, start_col_real; int color; int abn_style; int book_mark = 0; char line_stat[LINE_STATE_WIDTH + 1] = "\0"; if (row > w->lines - 1 - EDIT_TEXT_VERTICAL_OFFSET - 2 * (edit->fullscreen ? 0 : 1)) return; if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_COLOR)) book_mark = BOOK_MARK_COLOR; else if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_FOUND_COLOR)) book_mark = BOOK_MARK_FOUND_COLOR; if (book_mark) abn_style = book_mark << 16; else abn_style = MOD_ABNORMAL; end_col -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width; if (!edit->fullscreen) { end_col--; if (w->x + w->cols <= WIDGET (w->owner)->cols) end_col--; } color = edit_get_syntax_color (edit, b - 1); q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0); start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col; if (option_line_state) { unsigned int cur_line; cur_line = edit->start_line + row; if (cur_line <= (unsigned int) edit->buffer.lines) { g_snprintf (line_stat, LINE_STATE_WIDTH + 1, "%7i ", cur_line + 1); } else { memset (line_stat, ' ', LINE_STATE_WIDTH); line_stat[LINE_STATE_WIDTH] = '\0'; } if (book_mark_query_color (edit, cur_line, BOOK_MARK_COLOR)) { g_snprintf (line_stat, 2, "*"); } } if (col + 16 > -edit->start_col) { eval_marks (edit, &m1, &m2); if (row <= edit->buffer.lines - edit->start_line) { off_t tws = 0; if (tty_use_colors () && visible_tws) { unsigned int c; tws = edit_buffer_get_eol (&edit->buffer, b); while (tws > b && ((c = edit_buffer_get_byte (&edit->buffer, tws - 1)) == ' ' || c == '\t')) tws--; } while (col <= end_col - edit->start_col) { int char_length = 1; unsigned int c; gboolean wide_width_char = FALSE; gboolean control_char = FALSE; p->ch = 0; p->style = 0; if (q == edit->buffer.curs1) p->style |= MOD_CURSOR; if (q >= m1 && q < m2) { if (edit->column_highlight) { long x; long c1, c2; x = (long) edit_move_forward3 (edit, b, 0, q); c1 = min (edit->column1, edit->column2); c2 = max (edit->column1, edit->column2); if (x >= c1 && x < c2) p->style |= MOD_MARKED; } else p->style |= MOD_MARKED; } if (q == edit->bracket) p->style |= MOD_BOLD; if (q >= edit->found_start && q < (off_t) (edit->found_start + edit->found_len)) p->style |= MOD_BOLD; #ifdef HAVE_CHARSET if (edit->utf8) c = edit_buffer_get_utf (&edit->buffer, q, &char_length); else #endif c = edit_buffer_get_byte (&edit->buffer, q); /* we don't use bg for mc - fg contains both */ if (book_mark) { p->style |= book_mark << 16; } else { color = edit_get_syntax_color (edit, q); p->style |= color << 16; } switch (c) { case '\n': col = end_col - edit->start_col + 1; /* quit */ break; case '\t': { int tab_over; int i; i = TAB_SIZE - ((int) col % TAB_SIZE); tab_over = (end_col - edit->start_col) - (col + i - 1); if (tab_over < 0) i += tab_over; col += i; if (tty_use_colors () && ((visible_tabs || (visible_tws && q >= tws)) && enable_show_tabs_tws)) { if (p->style & MOD_MARKED) c = p->style; else if (book_mark) c |= book_mark << 16; else c = p->style | MOD_WHITESPACE; if (i > 2) { p->ch = '<'; p->style = c; p++; while (--i > 1) { p->ch = '-'; p->style = c; p++; } p->ch = '>'; p->style = c; p++; } else if (i > 1) { p->ch = '<'; p->style = c; p++; p->ch = '>'; p->style = c; p++; } else { p->ch = '>'; p->style = c; p++; } } else if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } else { p->ch |= ' '; c = p->style & ~MOD_CURSOR; p++; while (--i) { p->ch = ' '; p->style = c; p++; } } } break; case ' ': if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws) { p->ch = '.'; p->style |= MOD_WHITESPACE; p++; col++; break; } /* fallthrough */ default: #ifdef HAVE_CHARSET if (mc_global.utf8_display) { if (!edit->utf8) { c = convert_from_8bit_to_utf_c ((unsigned char) c, edit->converter); } else { if (g_unichar_iswide (c)) { wide_width_char = TRUE; col++; } } } else if (edit->utf8) c = convert_from_utf_to_current_c (c, edit->converter); else c = convert_to_display_c (c); #endif /* Caret notation for control characters */ if (c < 32) { p->ch = '^'; p->style = abn_style; p++; p->ch = c + 0x40; p->style = abn_style; p++; col += 2; control_char = TRUE; break; } if (c == 127) { p->ch = '^'; p->style = abn_style; p++; p->ch = '?'; p->style = abn_style; p++; col += 2; control_char = TRUE; break; } #ifdef HAVE_CHARSET if (edit->utf8) { if (g_unichar_isprint (c)) p->ch = c; else { p->ch = '.'; p->style = abn_style; } p++; } else #endif { if ((mc_global.utf8_display && g_unichar_isprint (c)) || (!mc_global.utf8_display && is_printable (c))) { p->ch = c; p++; } else { p->ch = '.'; p->style = abn_style; p++; } } col++; break; } /* case */ q++; if (char_length > 1) q += char_length - 1; if (col > (end_col - edit->start_col + 1)) { if (wide_width_char) { p--; break; } if (control_char) { p -= 2; break; } } } } } else { start_col_real = start_col = 0; } p->ch = 0; print_to_widget (edit, row, start_col, start_col_real, end_col, line, line_stat, book_mark); }
static void apply_rules_going_right (WEdit * edit, off_t i) { 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; 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 = 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 = 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; off_t 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 == 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 = 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) { int count; struct context_rule **rules = edit->rules; for (count = 1; rules[count] != NULL; count++) { r = 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 = 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; off_t 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; } } } edit->rule = _rule; }