edit.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,280 行 · 第 1/5 页
C
2,280 行
if (t) {
memcpy (t, edit->undo_stack, sizeof (long) * edit->stack_size);
free (edit->undo_stack);
edit->undo_stack = t;
edit->stack_size <<= 1;
edit->stack_size_mask = edit->stack_size - 1;
}
}
}
spm1 = (edit->stack_pointer - 1) & edit->stack_size_mask;
if (push_action_disabled)
return;
#ifdef FAST_MOVE_CURSOR
if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) {
va_list ap;
edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
va_start (ap, c);
c = -(va_arg (ap, int));
va_end (ap);
} else
#endif /* ! FAST_MOVE_CURSOR */
if (spm1 != edit->stack_bottom && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) {
int d;
if (edit->undo_stack[spm1] < 0) {
d = edit->undo_stack[(sp - 2) & edit->stack_size_mask];
if (d == c) {
if (edit->undo_stack[spm1] > -1000000000) {
if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */
edit->undo_stack[spm1]--;
return;
}
}
/* #define NO_STACK_CURSMOVE_ANIHILATION */
#ifndef NO_STACK_CURSMOVE_ANIHILATION
else if ((c == CURS_LEFT && d == CURS_RIGHT)
|| (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */
if (edit->undo_stack[spm1] == -2)
edit->stack_pointer = spm1;
else
edit->undo_stack[spm1]++;
return;
}
#endif
} else {
d = edit->undo_stack[spm1];
if (d == c) {
if (c >= KEY_PRESS)
return; /* --> no need to push multiple do-nothings */
edit->undo_stack[sp] = -2;
goto check_bottom;
}
#ifndef NO_STACK_CURSMOVE_ANIHILATION
else if ((c == CURS_LEFT && d == CURS_RIGHT)
|| (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */
edit->stack_pointer = spm1;
return;
}
#endif
}
}
edit->undo_stack[sp] = c;
check_bottom:
edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
/*if the sp wraps round and catches the stack_bottom then erase the first set of actions on the stack to make space - by moving stack_bottom forward one "key press" */
c = (edit->stack_pointer + 2) & edit->stack_size_mask;
if (c == edit->stack_bottom || ((c + 1) & edit->stack_size_mask) == edit->stack_bottom)
do {
edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask;
} while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
/*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */
if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS)
edit->stack_bottom = edit->stack_pointer = 0;
}
/*
TODO: if the user undos until the stack bottom, and the stack has not wrapped,
then the file should be as it was when he loaded up. Then set edit->modified to 0.
*/
long pop_action (WEdit * edit)
{
long c;
unsigned long sp = edit->stack_pointer;
if (sp == edit->stack_bottom) {
return STACK_BOTTOM;
}
sp = (sp - 1) & edit->stack_size_mask;
if ((c = edit->undo_stack[sp]) >= 0) {
/* edit->undo_stack[sp] = '@'; */
edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask;
return c;
}
if (sp == edit->stack_bottom) {
return STACK_BOTTOM;
}
c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
if (edit->undo_stack[sp] == -2) {
/* edit->undo_stack[sp] = '@'; */
edit->stack_pointer = sp;
} else
edit->undo_stack[sp]++;
return c;
}
/* is called whenever a modification is made by one of the four routines below */
static inline void edit_modification (WEdit * edit)
{
edit->modified = 1;
}
/*
Basic low level single character buffer alterations and movements at the cursor.
Returns char passed over, inserted or removed.
*/
void edit_insert (WEdit * edit, int c)
{
/* check if file has grown to large */
if (edit->last_byte >= SIZE_LIMIT)
return;
/* first we must update the position of the display window */
if (edit->curs1 < edit->start_display) {
edit->start_display++;
if (c == '\n')
edit->start_line++;
}
/* now we must update some info on the file and check if a redraw is required */
if (c == '\n') {
edit->curs_line++;
edit->total_lines++;
edit->force |= REDRAW_LINE_ABOVE | REDRAW_AFTER_CURSOR;
}
/* tell that we've modified the file */
edit_modification (edit);
/* save the reverse command onto the undo stack */
edit_push_action (edit, BACKSPACE);
/* update markers */
edit->mark1 += (edit->mark1 > edit->curs1);
edit->mark2 += (edit->mark2 > edit->curs1);
edit->last_get_rule += (edit->last_get_rule > edit->curs1);
/* add a new buffer if we've reached the end of the last one */
if (!(edit->curs1 & M_EDIT_BUF_SIZE))
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
/* perfprm the insertion */
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = (unsigned char) c;
/* update file length */
edit->last_byte++;
/* update cursor position */
edit->curs1++;
}
/* same as edit_insert and move left */
void edit_insert_ahead (WEdit * edit, int c)
{
if (edit->last_byte >= SIZE_LIMIT)
return;
if (edit->curs1 < edit->start_display) {
edit->start_display++;
if (c == '\n')
edit->start_line++;
}
if (c == '\n') {
edit->total_lines++;
edit->force |= REDRAW_AFTER_CURSOR;
}
edit_modification (edit);
edit_push_action (edit, DELETE);
edit->mark1 += (edit->mark1 >= edit->curs1);
edit->mark2 += (edit->mark2 >= edit->curs1);
edit->last_get_rule += (edit->last_get_rule >= edit->curs1);
if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
edit->last_byte++;
edit->curs2++;
}
int edit_delete (WEdit * edit)
{
int p;
if (!edit->curs2)
return 0;
edit->mark1 -= (edit->mark1 > edit->curs1);
edit->mark2 -= (edit->mark2 > edit->curs1);
edit->last_get_rule -= (edit->last_get_rule > edit->curs1);
p = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]);
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = NULL;
}
edit->last_byte--;
edit->curs2--;
if (p == '\n') {
edit->total_lines--;
edit->force |= REDRAW_AFTER_CURSOR;
}
edit_push_action (edit, p + 256);
if (edit->curs1 < edit->start_display) {
edit->start_display--;
if (p == '\n')
edit->start_line--;
}
edit_modification (edit);
return p;
}
int edit_backspace (WEdit * edit)
{
int p;
if (!edit->curs1)
return 0;
edit->mark1 -= (edit->mark1 >= edit->curs1);
edit->mark2 -= (edit->mark2 >= edit->curs1);
edit->last_get_rule -= (edit->last_get_rule >= edit->curs1);
p = *(edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE] + ((edit->curs1 - 1) & M_EDIT_BUF_SIZE));
if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) {
free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]);
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL;
}
edit->last_byte--;
edit->curs1--;
if (p == '\n') {
edit->curs_line--;
edit->total_lines--;
edit->force |= REDRAW_AFTER_CURSOR;
}
edit_push_action (edit, p);
if (edit->curs1 < edit->start_display) {
edit->start_display--;
if (p == '\n')
edit->start_line--;
}
edit_modification (edit);
return p;
}
#ifdef FAST_MOVE_CURSOR
#define memqcpy(edit,d,s,i) \
{ \
unsigned long next; \
char *dest = d; \
char *src = s; \
int n = i; \
while ((next = \
(unsigned long) memccpy (dest, src, '\n', n))) { \
edit->curs_line--; \
next -= (unsigned long) dest; \
n -= next; \
src += next; \
dest += next; \
} \
}
int edit_move_backward_lots (WEdit * edit, long increment)
{
int r, s, t;
char *p;
if (increment > edit->curs1)
increment = edit->curs1;
if (increment <= 0)
return -1;
edit_push_action (edit, CURS_RIGHT_LOTS, increment);
t = r = EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE);
if (r > increment)
r = increment;
s = edit->curs1 & M_EDIT_BUF_SIZE;
p = 0;
if (s > r) {
memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r,
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - r, r);
} else {
if (s) {
memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - s,
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE], s);
p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE];
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0;
}
memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r,
edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + EDIT_BUF_SIZE - (r - s), r - s);
}
increment -= r;
edit->curs1 -= r;
edit->curs2 += r;
if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
if (p)
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
else
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
} else {
if (p)
free (p);
}
s = edit->curs1 & M_EDIT_BUF_SIZE;
while (increment) {
p = 0;
r = EDIT_BUF_SIZE;
if (r > increment)
r = increment;
t = s;
if (r < t)
t = r;
memqcpy (edit,
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + EDIT_BUF_SIZE - t,
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - t,
t);
if (r >= s) {
if (t) {
p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE];
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0;
}
memqcpy (edit,
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + EDIT_BUF_SIZE - r,
edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + EDIT_BUF_SIZE - (r - s),
r - s);
}
increment -= r;
edit->curs1 -= r;
edit->curs2 += r;
if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
if (p)
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
else
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
} else {
if (p)
free (p);
}
}
return edit_get_byte (edit, edit->curs1);
}
#endif /* ! FAST_MOVE_CURSOR */
/* moves the curser right or left: increment positive or negative respectively */
int edit_cursor_move (WEdit * edit, long increment)
{
/* this is the same as a combination of two of the above routines, with only one push onto the undo stack */
int c;
#ifdef FAST_MOVE_CURSOR
if (increment < -256) {
edit->force |= REDRAW_PAGE;
return edit_move_backward_lots (edit, -increment);
}
#endif /* ! FAST_MOVE_CURSOR */
if (increment < 0) {
for (; increment < 0; increment++) {
if (!edit->curs1)
return -1;
edit_push_action (edit, CURS_RIGHT);
c = edit_get_byte (edit, edit->curs1 - 1);
if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
edit->curs2++;
c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE];
if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) {
free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]);
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL;
}
edit->curs1--;
if (c == '\n') {
edit->curs_line--;
edit->force |= REDRAW_LINE_BELOW;
}
}
return c;
} else if (increment > 0) {
for (; increment > 0; increment--) {
if (!edit->curs2)
return -2;
edit_push_action (edit, CURS_LEFT);
c = edit_get_byte (edit, edit->curs1);
if (!(edit->curs1 & M_EDIT_BUF_SIZE))
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c;
edit->curs1++;
c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]);
edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = 0;
}
edit->curs2--;
if (c == '\n') {
edit->curs_line++;
edit->force |= REDRAW_LINE_ABOVE;
}
}
return c;
} else
return -3;
}
/* These functions return positions relative to lines */
/* returns index of last char on line + 1 */
long edit_eol (WEdit * edit, long current)
{
if (current < edit->last_byte) {
for (;; current++)
#if 0
if (current == edit->last_byte || edit_get_byte (edit, current) == '\n')
#else
if (edit_get_byte (edit, current) == '\n')
#endif
break;
} else
return edit->last_byte;
return current;
}
/* returns index of first char on line */
long edit_bol (WEdit * edit, long current)
{
if (current > 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?