edit.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,280 行 · 第 1/5 页

C
2,280
字号
    edit->column2 = c2;
}


/* highlight marker toggle */
void edit_mark_cmd (WEdit * edit, int unmark)
{
    edit_push_markers (edit);
    if (unmark) {
	edit_set_markers (edit, 0, 0, 0, 0);
	edit->force |= REDRAW_PAGE;
    } else {
	if (edit->mark2 >= 0) {
	    edit_set_markers (edit, edit->curs1, -1, edit->curs_col, edit->curs_col);
	    edit->force |= REDRAW_PAGE;
	} else
	    edit_set_markers (edit, edit->mark1, edit->curs1, edit->column1, edit->curs_col);
    }
}

int my_type_of (int c)
{
    if (c < ' ' && c > 0)
	return 1;
    if (strchr ("+_-.", c))
	if (strchr (option_whole_chars_move, c))
	    return 3;
    if (!strcasechr (option_whole_chars_move, c))
	return 2;
    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c >= 160)
	return 3;
    return c;
}

void edit_left_word_move (WEdit * edit)
{
    do {
	edit_cursor_move (edit, -1);
	if (!edit->curs1)
	    break;
    } while (my_type_of (edit_get_byte (edit, edit->curs1))
	     ==
	     my_type_of (edit_get_byte (edit, edit->curs1 - 1)));
}

static void edit_left_word_move_cmd (WEdit * edit)
{
    edit_left_word_move (edit);
    if (strchr (option_whole_chars_move, ' '))
	if (strchr ("\t ", edit_get_byte (edit, edit->curs1)))
	    edit_left_word_move (edit);
    edit->force |= REDRAW_PAGE;
}

void edit_right_word_move (WEdit * edit)
{
    do {
	edit_cursor_move (edit, 1);
	if (edit->curs1 >= edit->last_byte)
	    break;
    } while (my_type_of (edit_get_byte (edit, edit->curs1 - 1))
	     ==
	     my_type_of (edit_get_byte (edit, edit->curs1)));
}

static void edit_right_word_move_cmd (WEdit * edit)
{
    edit_right_word_move (edit);
    if (strchr (option_whole_chars_move, ' '))
	if (strchr ("\t ", edit_get_byte (edit, edit->curs1)))
	    edit_right_word_move (edit);
    edit->force |= REDRAW_PAGE;
}


static void edit_right_delete_word (WEdit * edit)
{
    int c;
    do {
	c = edit_delete (edit);
    } while (my_type_of (c) == my_type_of (edit_get_byte (edit, edit->curs1)));
}

static void edit_left_delete_word (WEdit * edit)
{
    int c;
    do {
	c = edit_backspace (edit);
    } while (my_type_of (c) == my_type_of (edit_get_byte (edit, edit->curs1 - 1)));
}


/*
   the start column position is not recorded, and hence does not
   undo as it happed. But who would notice.
 */
void edit_do_undo (WEdit * edit)
{
    long ac;
    long count = 0;

    push_action_disabled = 1;	/* don't record undo's onto undo stack! */

    while ((ac = pop_action (edit)) < KEY_PRESS) {
	switch ((int) ac) {
	case STACK_BOTTOM:
	    goto done_undo;
	case CURS_RIGHT:
	    edit_cursor_move (edit, 1);
	    break;
	case CURS_LEFT:
	    edit_cursor_move (edit, -1);
	    break;
	case BACKSPACE:
	    edit_backspace (edit);
	    break;
	case DELETE:
	    edit_delete (edit);
	    break;
	}
	if (ac >= 256 && ac < 512)
	    edit_insert_ahead (edit, ac - 256);
	if (ac >= 0 && ac < 256)
	    edit_insert (edit, ac);

	if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) {
	    edit->mark1 = ac - MARK_1;
	} else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) {
	    edit->mark2 = ac - MARK_2;
	}
	if (count++)
	    edit->force |= REDRAW_PAGE;		/* more than one pop usually means something big */
    }

    if (edit->start_display > ac - KEY_PRESS) {
	edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display);
	edit->force |= REDRAW_PAGE;
    } else if (edit->start_display < ac - KEY_PRESS) {
	edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS);
	edit->force |= REDRAW_PAGE;
    }
    edit->start_display = ac - KEY_PRESS;	/* see push and pop above */
    edit_update_curs_row(edit);

    done_undo:;
    push_action_disabled = 0;
}

static void edit_delete_to_line_end (WEdit * edit)
{
    for (;;) {
	if (edit_get_byte (edit, edit->curs1) == '\n')
	    break;
	if (!edit->curs2)
	    break;
	edit_delete (edit);
    }
}

static void edit_delete_to_line_begin (WEdit * edit)
{
    for (;;) {
	if (edit_get_byte (edit, edit->curs1 - 1) == '\n')
	    break;
	if (!edit->curs1)
	    break;
	edit_backspace (edit);
    }
}

static void edit_delete_line (WEdit * edit)
{
    int c;
    do {
	c = edit_delete (edit);
    } while (c != '\n' && c);
    do {
	c = edit_backspace (edit);
    } while (c != '\n' && c);
    if (c)
	edit_insert (edit, '\n');
}

static void insert_spaces_tab (WEdit * edit)
{
    int i = option_tab_spacing;
    while (i--)
	edit_insert (edit, ' ');
}

static int is_aligned_on_a_tab (WEdit * edit)
{
    edit_update_curs_col (edit);
    if ((edit->curs_col % (TAB_SIZE * space_width)) && edit->curs_col % (TAB_SIZE * space_width) != (HALF_TAB_SIZE * space_width))
	return 0;		/* not alligned on a tab */
    return 1;
}

static int right_of_four_spaces (WEdit *edit)
{
    int i, ch = 0;
    for (i = 1; i <= HALF_TAB_SIZE; i++)
	ch |= edit_get_byte (edit, edit->curs1 - i);
    if (ch == ' ')
	return is_aligned_on_a_tab (edit);
    return 0;
}

static int left_of_four_spaces (WEdit *edit)
{
    int i, ch = 0;
    for (i = 0; i < HALF_TAB_SIZE; i++)
	ch |= edit_get_byte (edit, edit->curs1 + i);
    if (ch == ' ')
	return is_aligned_on_a_tab (edit);
    return 0;
}

int edit_indent_width (WEdit * edit, long p)
{
    long q = p;
    while (strchr ("\t ", edit_get_byte (edit, q)) && q < edit->last_byte - 1)	/* move to the end of the leading whitespace of the line */
	q++;
    return edit_move_forward3 (edit, p, 0, q);	/* count the number of columns of indentation */
}

void edit_insert_indent (WEdit * edit, int indent)
{
#ifndef MIDNIGHT
    indent /= space_width;
#endif
    if (!option_fill_tabs_with_spaces) {
	while (indent >= TAB_SIZE) {
	    edit_insert (edit, '\t');
	    indent -= TAB_SIZE;
	}
    }
    while (indent--)
	edit_insert (edit, ' ');
}

static void edit_auto_indent (WEdit * edit, int always)
{
    long p;
    int indent;
    p = edit->curs1;
    while (strchr ("\t\n\r ", edit_get_byte (edit, p - 1)) && p > 0)	/* move back/up to a line with text */
	p--;
    indent = edit_indent_width (edit, edit_bol (edit, p));
    if (edit->curs_col < indent)
	indent = edit->curs_col;
    edit_insert_indent (edit, indent);
}

static void edit_double_newline (WEdit * edit)
{
    edit_insert (edit, '\n');
    if (edit_get_byte (edit, edit->curs1) == '\n')
	return;
    if (edit_get_byte (edit, edit->curs1 - 2) == '\n')
	return;
    edit->force |= REDRAW_PAGE;
    edit_insert (edit, '\n');
}

static void edit_tab_cmd (WEdit * edit)
{
    int i;

    if (option_fake_half_tabs) {
	if (is_in_indent (edit)) {
	    /*insert a half tab (usually four spaces) unless there is a
	       half tab already behind, then delete it and insert a
	       full tab. */
	    if (right_of_four_spaces (edit)) {
		for (i = 1; i <= HALF_TAB_SIZE; i++)
		    edit_backspace (edit);
		if (option_fill_tabs_with_spaces) {
		    insert_spaces_tab (edit);
		} else {
		    edit_insert (edit, '\t');
		}
	    } else {
		for (i = 1; i <= HALF_TAB_SIZE; i++)
		    edit_insert (edit, ' ');
	    }
	    return;
	}
    }
    if (option_fill_tabs_with_spaces) {
	insert_spaces_tab (edit);
    } else {
	edit_insert (edit, '\t');
    }
    return;
}

void format_paragraph (WEdit * edit, int force);

static void check_and_wrap_line (WEdit * edit)
{
    int curs, c;
    if (!option_typewriter_wrap)
	return;
    edit_update_curs_col (edit);
#ifdef MIDNIGHT
    if (edit->curs_col < option_word_wrap_line_length)
#else
    if (edit->curs_col < option_word_wrap_line_length * FONT_MEAN_WIDTH)
#endif
	return;
    curs = edit->curs1;
    for (;;) {
	curs--;
	c = edit_get_byte (edit, curs);
	if (c == '\n' || curs <= 0) {
	    edit_insert (edit, '\n');
	    return;
	}
	if (c == ' ' || c == '\t') {
	    int current = edit->curs1;
	    edit_cursor_move (edit, curs - edit->curs1 + 1);
	    edit_insert (edit, '\n');
	    edit_cursor_move (edit, current - edit->curs1 + 1);
	    return;
	}
    }
}

void edit_execute_macro (WEdit * edit, struct macro macro[], int n);

/* either command or char_for_insertion must be passed as -1 */
int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion);

#ifdef MIDNIGHT
int edit_translate_key (WEdit * edit, unsigned int x_keycode, long x_key, int x_state, int *cmd, int *ch)
{
    int command = -1;
    int char_for_insertion = -1;

#include "edit_key_translator.c"

    *cmd = command;
    *ch = char_for_insertion;

    if((command == -1 || command == 0) && char_for_insertion == -1)  /* unchanged, key has no function here */
	return 0;
    return 1;
}
#endif

void edit_push_key_press (WEdit * edit)
{
    edit_push_action (edit, KEY_PRESS + edit->start_display);
    if (edit->mark2 == -1)
	edit_push_action (edit, MARK_1 + edit->mark1);
}

/* this find the matching bracket in either direction, and sets edit->bracket */
void edit_find_bracket (WEdit * edit)
{
    if (option_find_bracket) {
	const char *b = "{}{[][()(", *p;
	static int last_bracket = -1;
	int i = 1, a, inc = -1, c, d, n = 0, j = 0;
	long q;

	edit->bracket = -1;
	c = edit_get_byte (edit, edit->curs1);
	p = strchr (b, c);
	edit_update_curs_row (edit);
	if (p) {
	    d = p[1];
	    if (strchr ("{[(", c))
		inc = 1;
	    for (q = edit->curs1 + inc;; q += inc) {
		if (q >= edit->last_byte || q < edit->start_display || j++ > 10000)
		    break;
		a = edit_get_byte (edit, q);
		if (inc > 0 && a == '\n')
		    n++;
		if (n >= edit->num_widget_lines - edit->curs_row)	/* out of screen */
		    break;
		i += (a == c) - (a == d);
		if (!i) {
		    edit->bracket = q;
		    break;
		}
	    }
	}
	if (last_bracket != edit->bracket)
	    edit->force |= REDRAW_PAGE;
	last_bracket = edit->bracket;
    }
}


/* this executes a command as though the user initiated it through a key press. */
/* callback with WIDGET_KEY as a message calls this after translating the key
   press */
/* this can be used to pass any command to the editor. Same as sendevent with
   msg = WIDGET_COMMAND and par = command  except the screen wouldn't update */
/* one of command or char_for_insertion must be passed as -1 */
/* commands are executed, and char_for_insertion is inserted at the cursor */
/* returns 0 if the command is a macro that was not found, 1 otherwise */
int edit_execute_key_command (WEdit * edit, int command, int char_for_insertion)
{
    int r;
    if (command == CK_Begin_Record_Macro) {
	edit->macro_i = 0;
	edit->force |= REDRAW_CHAR_ONLY | REDRAW_LINE;
	return command;
    }
    if (command == CK_End_Record_Macro && edit->macro_i != -1) {
	edit->force |= REDRAW_COMPLETELY;
	edit_save_macro_cmd (edit, edit->macro, edit->macro_i);
	edit->macro_i = -1;
	return command;
    }
    if (edit->macro_i >= 0 && edit->macro_i < MAX_MACRO_LENGTH - 1) {
	edit->macro[edit->macro_i].command = command;
	edit->macro[edit->macro_i++].ch = char_for_insertion;
    }
/* record the beginning of a set of editing actions initiated by a key press */
    if (command != CK_Undo)
	edit_push_key_press (edit);

    r = edit_execute_cmd (edit, command, char_for_insertion);

    return r;
}

#ifdef MIDNIGHT
static const char *shell_cmd[] = SHELL_COMMANDS_i
#else
static void (*user_commamd) (WEdit *, int) = 0;
void edit_set_user_command (void (*func) (WEdit *, int))
{
    user_commamd = func;
}

#endif

void edit_mail_dialog (WEdit * edit);

/*
   This executes a command at a lower level than macro recording.
   It also does not push a key_press onto the undo stack. This means
   that if it is called many times, a single undo command will undo
   all of them. It also does not check for the Undo command.
   Returns 0 if the command is a macro that was not found, 1
   otherwise.
 */
int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion)
{
    int result = 1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?